]> git.saurik.com Git - apple/network_cmds.git/commitdiff
network_cmds-76.tar.gz mac-os-x-100 v76
authorApple <opensource@apple.com>
Tue, 10 Apr 2001 09:43:13 +0000 (09:43 +0000)
committerApple <opensource@apple.com>
Tue, 10 Apr 2001 09:43:13 +0000 (09:43 +0000)
729 files changed:
Makefile [new file with mode: 0644]
Makefile.include [new file with mode: 0644]
Makefile.preamble [new file with mode: 0644]
PB.project [new file with mode: 0644]
alias/Makefile [new file with mode: 0644]
alias/Makefile.postamble [new file with mode: 0644]
alias/Makefile.preamble [new file with mode: 0644]
alias/PB.project [new file with mode: 0644]
alias/alias.c [new file with mode: 0644]
alias/alias.h [new file with mode: 0644]
alias/alias_cuseeme.c [new file with mode: 0644]
alias/alias_db.c [new file with mode: 0644]
alias/alias_ftp.c [new file with mode: 0644]
alias/alias_irc.c [new file with mode: 0644]
alias/alias_local.h [new file with mode: 0644]
alias/alias_nbt.c [new file with mode: 0644]
alias/alias_proxy.c [new file with mode: 0644]
alias/alias_util.c [new file with mode: 0644]
arp.tproj/Makefile [new file with mode: 0644]
arp.tproj/Makefile.postamble [new file with mode: 0644]
arp.tproj/Makefile.preamble [new file with mode: 0644]
arp.tproj/PB.project [new file with mode: 0644]
arp.tproj/arp.8 [new file with mode: 0644]
arp.tproj/arp.c [new file with mode: 0644]
arp.tproj/arp4.4 [new file with mode: 0644]
bootparams/Makefile [new file with mode: 0644]
bootparams/Makefile.postamble [new file with mode: 0644]
bootparams/Makefile.preamble [new file with mode: 0644]
bootparams/PB.project [new file with mode: 0644]
bootparams/bootparamd.tproj/Makefile [new file with mode: 0644]
bootparams/bootparamd.tproj/Makefile.postamble [new file with mode: 0644]
bootparams/bootparamd.tproj/Makefile.preamble [new file with mode: 0644]
bootparams/bootparamd.tproj/PB.project [new file with mode: 0644]
bootparams/bootparamd.tproj/bootparam_proc.c [new file with mode: 0644]
bootparams/bootparamd.tproj/bootparamd.c [new file with mode: 0644]
bootparams/bootparams/Makefile [new file with mode: 0644]
bootparams/bootparams/Makefile.postamble [new file with mode: 0644]
bootparams/bootparams/Makefile.preamble [new file with mode: 0644]
bootparams/bootparams/PB.project [new file with mode: 0644]
bootparams/bootparams/bootparam_prot.x [new file with mode: 0644]
bootparams/bpwhoami.tproj/Makefile [new file with mode: 0644]
bootparams/bpwhoami.tproj/Makefile.postamble [new file with mode: 0644]
bootparams/bpwhoami.tproj/Makefile.preamble [new file with mode: 0644]
bootparams/bpwhoami.tproj/PB.project [new file with mode: 0644]
bootparams/bpwhoami.tproj/bpwhoami.c [new file with mode: 0644]
domainname.tproj/Makefile [new file with mode: 0644]
domainname.tproj/Makefile.dist [new file with mode: 0644]
domainname.tproj/PB.project [new file with mode: 0644]
domainname.tproj/domainname.1 [new file with mode: 0644]
domainname.tproj/domainname.c [new file with mode: 0644]
ftp.tproj/Makefile [new file with mode: 0644]
ftp.tproj/Makefile.postamble [new file with mode: 0644]
ftp.tproj/Makefile.preamble [new file with mode: 0644]
ftp.tproj/PB.project [new file with mode: 0644]
ftp.tproj/cmds.c [new file with mode: 0644]
ftp.tproj/cmdtab.c [new file with mode: 0644]
ftp.tproj/domacro.c [new file with mode: 0644]
ftp.tproj/extern.h [new file with mode: 0644]
ftp.tproj/ftp.1 [new file with mode: 0644]
ftp.tproj/ftp.c [new file with mode: 0644]
ftp.tproj/ftp_var.c [new file with mode: 0644]
ftp.tproj/ftp_var.h [new file with mode: 0644]
ftp.tproj/h.template [new file with mode: 0644]
ftp.tproj/m.template [new file with mode: 0644]
ftp.tproj/main.c [new file with mode: 0644]
ftp.tproj/pathnames.h [new file with mode: 0644]
ftp.tproj/ruserpass.c [new file with mode: 0644]
ftpd.tproj/Makefile [new file with mode: 0644]
ftpd.tproj/Makefile.postamble [new file with mode: 0644]
ftpd.tproj/Makefile.preamble [new file with mode: 0644]
ftpd.tproj/PB.project [new file with mode: 0644]
ftpd.tproj/extern.h [new file with mode: 0644]
ftpd.tproj/ftpcmd.y [new file with mode: 0644]
ftpd.tproj/ftpd.8 [new file with mode: 0644]
ftpd.tproj/ftpd.c [new file with mode: 0644]
ftpd.tproj/logwtmp.c [new file with mode: 0644]
ftpd.tproj/pathnames.h [new file with mode: 0644]
ftpd.tproj/popen.c [new file with mode: 0644]
ftpd.tproj/vers.c [new file with mode: 0644]
identd.tproj/CREDITS [new file with mode: 0644]
identd.tproj/Makefile [new file with mode: 0644]
identd.tproj/Makefile.dist [new file with mode: 0644]
identd.tproj/Makefile.preamble [new file with mode: 0644]
identd.tproj/PB.project [new file with mode: 0644]
identd.tproj/README [new file with mode: 0644]
identd.tproj/config.c [new file with mode: 0644]
identd.tproj/error.h [new file with mode: 0644]
identd.tproj/identd.8 [new file with mode: 0644]
identd.tproj/identd.c [new file with mode: 0644]
identd.tproj/identd.h [new file with mode: 0644]
identd.tproj/netbsd.c [new file with mode: 0644]
identd.tproj/parse.c [new file with mode: 0644]
identd.tproj/proxy.c [new file with mode: 0644]
identd.tproj/version.c [new file with mode: 0644]
identd.tproj/xpaths.h [new file with mode: 0644]
ifconfig.tproj/Makefile [new file with mode: 0644]
ifconfig.tproj/Makefile.dist [new file with mode: 0644]
ifconfig.tproj/Makefile.postamble [new file with mode: 0644]
ifconfig.tproj/Makefile.preamble [new file with mode: 0644]
ifconfig.tproj/PB.project [new file with mode: 0644]
ifconfig.tproj/ifconfig.8 [new file with mode: 0644]
ifconfig.tproj/ifconfig.c [new file with mode: 0644]
ifconfig.tproj/ifconfig.h [new file with mode: 0644]
ifconfig.tproj/ifmedia.c [new file with mode: 0644]
inetd.tproj/Makefile [new file with mode: 0644]
inetd.tproj/Makefile.postamble [new file with mode: 0644]
inetd.tproj/Makefile.preamble [new file with mode: 0644]
inetd.tproj/PB.project [new file with mode: 0644]
inetd.tproj/inetd.8 [new file with mode: 0644]
inetd.tproj/inetd.c [new file with mode: 0644]
inetd.tproj/pathnames.h [new file with mode: 0644]
ipfw.tproj/Makefile [new file with mode: 0644]
ipfw.tproj/Makefile.postamble [new file with mode: 0644]
ipfw.tproj/Makefile.preamble [new file with mode: 0644]
ipfw.tproj/PB.project [new file with mode: 0644]
ipfw.tproj/ipfw.8 [new file with mode: 0644]
ipfw.tproj/ipfw.c [new file with mode: 0644]
logger.tproj/Makefile [new file with mode: 0644]
logger.tproj/Makefile.postamble [new file with mode: 0644]
logger.tproj/Makefile.preamble [new file with mode: 0644]
logger.tproj/PB.project [new file with mode: 0644]
logger.tproj/h.template [new file with mode: 0644]
logger.tproj/logger.1 [new file with mode: 0644]
logger.tproj/logger.c [new file with mode: 0644]
logger.tproj/m.template [new file with mode: 0644]
makedbm.tproj/Makefile [new file with mode: 0644]
makedbm.tproj/Makefile.postamble [new file with mode: 0644]
makedbm.tproj/Makefile.preamble [new file with mode: 0644]
makedbm.tproj/PB.project [new file with mode: 0644]
makedbm.tproj/db.c [new file with mode: 0644]
makedbm.tproj/db.h [new file with mode: 0644]
makedbm.tproj/makedbm.8 [new file with mode: 0644]
makedbm.tproj/makedbm.c [new file with mode: 0644]
makedbm.tproj/ypdb.c [new file with mode: 0644]
makedbm.tproj/ypdb.h [new file with mode: 0644]
makedbm.tproj/ypdef.h [new file with mode: 0644]
natd.tproj/Makefile [new file with mode: 0644]
natd.tproj/Makefile.postamble [new file with mode: 0644]
natd.tproj/Makefile.preamble [new file with mode: 0644]
natd.tproj/PB.project [new file with mode: 0644]
natd.tproj/icmp.c [new file with mode: 0644]
natd.tproj/natd.8 [new file with mode: 0644]
natd.tproj/natd.c [new file with mode: 0644]
natd.tproj/natd.h [new file with mode: 0644]
netstat.tproj/DERIVED_FILES [new file with mode: 0644]
netstat.tproj/Makefile [new file with mode: 0644]
netstat.tproj/Makefile.postamble [new file with mode: 0644]
netstat.tproj/Makefile.preamble [new file with mode: 0644]
netstat.tproj/PB.project [new file with mode: 0644]
netstat.tproj/data.c [new file with mode: 0644]
netstat.tproj/if.c [new file with mode: 0644]
netstat.tproj/inet.c [new file with mode: 0644]
netstat.tproj/iso.c [new file with mode: 0644]
netstat.tproj/main.c [new file with mode: 0644]
netstat.tproj/mbuf.c [new file with mode: 0644]
netstat.tproj/mroute.c [new file with mode: 0644]
netstat.tproj/netstat.1 [new file with mode: 0644]
netstat.tproj/netstat.h [new file with mode: 0644]
netstat.tproj/route.c [new file with mode: 0644]
netstat.tproj/tp_astring.c [new file with mode: 0644]
netstat.tproj/unix.c [new file with mode: 0644]
newclient.tproj/Makefile [new file with mode: 0644]
newclient.tproj/Makefile.preamble [new file with mode: 0644]
newclient.tproj/PB.project [new file with mode: 0644]
newclient.tproj/newclient.csh [new file with mode: 0644]
nfsd.tproj/Makefile [new file with mode: 0644]
nfsd.tproj/Makefile.dist [new file with mode: 0644]
nfsd.tproj/Makefile.preamble [new file with mode: 0644]
nfsd.tproj/PB.project [new file with mode: 0644]
nfsd.tproj/nfsd.8 [new file with mode: 0644]
nfsd.tproj/nfsd.c [new file with mode: 0644]
nfsiod.tproj/Makefile [new file with mode: 0644]
nfsiod.tproj/Makefile.dist [new file with mode: 0644]
nfsiod.tproj/Makefile.preamble [new file with mode: 0644]
nfsiod.tproj/PB.project [new file with mode: 0644]
nfsiod.tproj/nfsiod.8 [new file with mode: 0644]
nfsiod.tproj/nfsiod.c [new file with mode: 0644]
nfsstat.tproj/Makefile [new file with mode: 0644]
nfsstat.tproj/Makefile.postamble [new file with mode: 0644]
nfsstat.tproj/Makefile.preamble [new file with mode: 0644]
nfsstat.tproj/PB.project [new file with mode: 0644]
nfsstat.tproj/nfsstat.1 [new file with mode: 0644]
nfsstat.tproj/nfsstat.c [new file with mode: 0644]
pcap/Makefile [new file with mode: 0644]
pcap/Makefile.postamble [new file with mode: 0644]
pcap/Makefile.preamble [new file with mode: 0644]
pcap/PB.project [new file with mode: 0644]
pcap/bpf_filter.c [new file with mode: 0644]
pcap/bpf_image.c [new file with mode: 0644]
pcap/etherent.c [new file with mode: 0644]
pcap/ethertype.h [new file with mode: 0644]
pcap/gencode.c [new file with mode: 0644]
pcap/gencode.h [new file with mode: 0644]
pcap/grammar.y [new file with mode: 0644]
pcap/inet.c [new file with mode: 0644]
pcap/nametoaddr.c [new file with mode: 0644]
pcap/optimize.c [new file with mode: 0644]
pcap/pcap-bpf.c [new file with mode: 0644]
pcap/pcap-int.h [new file with mode: 0644]
pcap/pcap-namedb.h [new file with mode: 0644]
pcap/pcap.c [new file with mode: 0644]
pcap/pcap.h [new file with mode: 0644]
pcap/savefile.c [new file with mode: 0644]
pcap/scanner.l [new file with mode: 0644]
ping.tproj/Makefile [new file with mode: 0644]
ping.tproj/Makefile.dist [new file with mode: 0644]
ping.tproj/Makefile.postamble [new file with mode: 0644]
ping.tproj/Makefile.preamble [new file with mode: 0644]
ping.tproj/PB.project [new file with mode: 0644]
ping.tproj/ping.8 [new file with mode: 0644]
ping.tproj/ping.c [new file with mode: 0644]
portmap.tproj/Makefile [new file with mode: 0644]
portmap.tproj/Makefile.postamble [new file with mode: 0644]
portmap.tproj/Makefile.preamble [new file with mode: 0644]
portmap.tproj/PB.project [new file with mode: 0644]
portmap.tproj/portmap.8 [new file with mode: 0644]
portmap.tproj/portmap.c [new file with mode: 0644]
rarpd.tproj/Makefile [new file with mode: 0644]
rarpd.tproj/Makefile.dist [new file with mode: 0644]
rarpd.tproj/Makefile.preamble [new file with mode: 0644]
rarpd.tproj/PB.project [new file with mode: 0644]
rarpd.tproj/rarpd.8 [new file with mode: 0644]
rarpd.tproj/rarpd.c [new file with mode: 0644]
rbootd.tproj/Makefile [new file with mode: 0644]
rbootd.tproj/Makefile.postamble [new file with mode: 0644]
rbootd.tproj/Makefile.preamble [new file with mode: 0644]
rbootd.tproj/PB.project [new file with mode: 0644]
rbootd.tproj/bpf.c [new file with mode: 0644]
rbootd.tproj/conf.c [new file with mode: 0644]
rbootd.tproj/defs.h [new file with mode: 0644]
rbootd.tproj/parseconf.c [new file with mode: 0644]
rbootd.tproj/pathnames.h [new file with mode: 0644]
rbootd.tproj/rbootd.8 [new file with mode: 0644]
rbootd.tproj/rbootd.c [new file with mode: 0644]
rbootd.tproj/rmp.h [new file with mode: 0644]
rbootd.tproj/rmp_var.h [new file with mode: 0644]
rbootd.tproj/rmpproto.c [new file with mode: 0644]
rbootd.tproj/utils.c [new file with mode: 0644]
rcp.tproj/Makefile [new file with mode: 0644]
rcp.tproj/Makefile.dist [new file with mode: 0644]
rcp.tproj/Makefile.postamble [new file with mode: 0644]
rcp.tproj/Makefile.preamble [new file with mode: 0644]
rcp.tproj/PB.project [new file with mode: 0644]
rcp.tproj/extern.h [new file with mode: 0644]
rcp.tproj/pathnames.h [new file with mode: 0644]
rcp.tproj/rcp.1 [new file with mode: 0644]
rcp.tproj/rcp.c [new file with mode: 0644]
rcp.tproj/util.c [new file with mode: 0644]
revnetgroup.tproj/Makefile [new file with mode: 0644]
revnetgroup.tproj/Makefile.postamble [new file with mode: 0644]
revnetgroup.tproj/Makefile.preamble [new file with mode: 0644]
revnetgroup.tproj/PB.project [new file with mode: 0644]
revnetgroup.tproj/hash.c [new file with mode: 0644]
revnetgroup.tproj/hash.h [new file with mode: 0644]
revnetgroup.tproj/parse_netgroup.c [new file with mode: 0644]
revnetgroup.tproj/revnetgroup.8 [new file with mode: 0644]
revnetgroup.tproj/revnetgroup.c [new file with mode: 0644]
rexecd.tproj/Makefile [new file with mode: 0644]
rexecd.tproj/Makefile.postamble [new file with mode: 0644]
rexecd.tproj/Makefile.preamble [new file with mode: 0644]
rexecd.tproj/PB.project [new file with mode: 0644]
rexecd.tproj/rexecd.8 [new file with mode: 0644]
rexecd.tproj/rexecd.c [new file with mode: 0644]
rlogin.tproj/Makefile [new file with mode: 0644]
rlogin.tproj/Makefile.postamble [new file with mode: 0644]
rlogin.tproj/Makefile.preamble [new file with mode: 0644]
rlogin.tproj/PB.project [new file with mode: 0644]
rlogin.tproj/des_rw.c [new file with mode: 0644]
rlogin.tproj/kcmd.c [new file with mode: 0644]
rlogin.tproj/krb.h [new file with mode: 0644]
rlogin.tproj/krcmd.c [new file with mode: 0644]
rlogin.tproj/rlogin.1 [new file with mode: 0644]
rlogin.tproj/rlogin.c [new file with mode: 0644]
rlogind.tproj/Makefile [new file with mode: 0644]
rlogind.tproj/Makefile.postamble [new file with mode: 0644]
rlogind.tproj/Makefile.preamble [new file with mode: 0644]
rlogind.tproj/PB.project [new file with mode: 0644]
rlogind.tproj/pathnames.h [new file with mode: 0644]
rlogind.tproj/rlogind.8 [new file with mode: 0644]
rlogind.tproj/rlogind.c [new file with mode: 0644]
route.tproj/Makefile [new file with mode: 0644]
route.tproj/Makefile.dist [new file with mode: 0644]
route.tproj/Makefile.postamble [new file with mode: 0644]
route.tproj/Makefile.preamble [new file with mode: 0644]
route.tproj/PB.project [new file with mode: 0644]
route.tproj/ccitt_addr.c [new file with mode: 0644]
route.tproj/keywords.h [new file with mode: 0644]
route.tproj/route.8 [new file with mode: 0644]
route.tproj/route.c [new file with mode: 0644]
routed.tproj/Makefile [new file with mode: 0644]
routed.tproj/Makefile.dist [new file with mode: 0644]
routed.tproj/Makefile.preamble [new file with mode: 0644]
routed.tproj/PB.project [new file with mode: 0644]
routed.tproj/af.c [new file with mode: 0644]
routed.tproj/af.h [new file with mode: 0644]
routed.tproj/defs.c [new file with mode: 0644]
routed.tproj/defs.h [new file with mode: 0644]
routed.tproj/if.c [new file with mode: 0644]
routed.tproj/inet.c [new file with mode: 0644]
routed.tproj/input.c [new file with mode: 0644]
routed.tproj/interface.h [new file with mode: 0644]
routed.tproj/main.c [new file with mode: 0644]
routed.tproj/output.c [new file with mode: 0644]
routed.tproj/pathnames.h [new file with mode: 0644]
routed.tproj/routed.8 [new file with mode: 0644]
routed.tproj/startup.c [new file with mode: 0644]
routed.tproj/table.h [new file with mode: 0644]
routed.tproj/tables.c [new file with mode: 0644]
routed.tproj/timer.c [new file with mode: 0644]
routed.tproj/trace.c [new file with mode: 0644]
routed.tproj/trace.h [new file with mode: 0644]
rpc_yppasswdd.tproj/Makefile [new file with mode: 0644]
rpc_yppasswdd.tproj/Makefile.postamble [new file with mode: 0644]
rpc_yppasswdd.tproj/Makefile.preamble [new file with mode: 0644]
rpc_yppasswdd.tproj/PB.project [new file with mode: 0644]
rpc_yppasswdd.tproj/passwd.c [new file with mode: 0644]
rpc_yppasswdd.tproj/rpc.yppasswdd.8 [new file with mode: 0644]
rpc_yppasswdd.tproj/rpc.yppasswdd.c [new file with mode: 0644]
rpc_yppasswdd.tproj/yppasswd.h [new file with mode: 0644]
rpc_yppasswdd.tproj/yppasswdd_mkpw.c [new file with mode: 0644]
rpc_yppasswdd.tproj/yppasswdd_proc.c [new file with mode: 0644]
rpcinfo.tproj/Makefile [new file with mode: 0644]
rpcinfo.tproj/Makefile.postamble [new file with mode: 0644]
rpcinfo.tproj/Makefile.preamble [new file with mode: 0644]
rpcinfo.tproj/PB.project [new file with mode: 0644]
rpcinfo.tproj/h.template [new file with mode: 0644]
rpcinfo.tproj/m.template [new file with mode: 0644]
rpcinfo.tproj/rpcinfo.c [new file with mode: 0644]
rsh.tproj/Makefile [new file with mode: 0644]
rsh.tproj/Makefile.postamble [new file with mode: 0644]
rsh.tproj/Makefile.preamble [new file with mode: 0644]
rsh.tproj/PB.project [new file with mode: 0644]
rsh.tproj/pathnames.h [new file with mode: 0644]
rsh.tproj/rsh.1 [new file with mode: 0644]
rsh.tproj/rsh.c [new file with mode: 0644]
rshd.tproj/Makefile [new file with mode: 0644]
rshd.tproj/Makefile.postamble [new file with mode: 0644]
rshd.tproj/Makefile.preamble [new file with mode: 0644]
rshd.tproj/PB.project [new file with mode: 0644]
rshd.tproj/rshd.8 [new file with mode: 0644]
rshd.tproj/rshd.c [new file with mode: 0644]
ruptime.tproj/Makefile [new file with mode: 0644]
ruptime.tproj/Makefile.dist [new file with mode: 0644]
ruptime.tproj/Makefile.postamble [new file with mode: 0644]
ruptime.tproj/Makefile.preamble [new file with mode: 0644]
ruptime.tproj/PB.project [new file with mode: 0644]
ruptime.tproj/h.template [new file with mode: 0644]
ruptime.tproj/m.template [new file with mode: 0644]
ruptime.tproj/ruptime.1 [new file with mode: 0644]
ruptime.tproj/ruptime.c [new file with mode: 0644]
rwho.tproj/Makefile [new file with mode: 0644]
rwho.tproj/Makefile.dist [new file with mode: 0644]
rwho.tproj/Makefile.postamble [new file with mode: 0644]
rwho.tproj/Makefile.preamble [new file with mode: 0644]
rwho.tproj/PB.project [new file with mode: 0644]
rwho.tproj/rwho.1 [new file with mode: 0644]
rwho.tproj/rwho.c [new file with mode: 0644]
rwhod.tproj/Makefile [new file with mode: 0644]
rwhod.tproj/Makefile.postamble [new file with mode: 0644]
rwhod.tproj/Makefile.preamble [new file with mode: 0644]
rwhod.tproj/PB.project [new file with mode: 0644]
rwhod.tproj/rwhod.8 [new file with mode: 0644]
rwhod.tproj/rwhod.c [new file with mode: 0644]
slattach.tproj/Makefile [new file with mode: 0644]
slattach.tproj/Makefile.dist [new file with mode: 0644]
slattach.tproj/Makefile.preamble [new file with mode: 0644]
slattach.tproj/PB.project [new file with mode: 0644]
slattach.tproj/slattach.8 [new file with mode: 0644]
slattach.tproj/slattach.c [new file with mode: 0644]
sliplogin.tproj/Makefile [new file with mode: 0644]
sliplogin.tproj/Makefile.postamble [new file with mode: 0644]
sliplogin.tproj/Makefile.preamble [new file with mode: 0644]
sliplogin.tproj/PB.project [new file with mode: 0644]
sliplogin.tproj/pathnames.h [new file with mode: 0644]
sliplogin.tproj/slip.hosts [new file with mode: 0644]
sliplogin.tproj/slip.login [new file with mode: 0644]
sliplogin.tproj/sliplogin.8 [new file with mode: 0644]
sliplogin.tproj/sliplogin.c [new file with mode: 0644]
spray.tproj/Makefile [new file with mode: 0644]
spray.tproj/Makefile.dist [new file with mode: 0644]
spray.tproj/Makefile.postamble [new file with mode: 0644]
spray.tproj/Makefile.preamble [new file with mode: 0644]
spray.tproj/PB.project [new file with mode: 0644]
spray.tproj/spray.c [new file with mode: 0644]
spray.tproj/spray.x [new file with mode: 0644]
startslip.tproj/Makefile [new file with mode: 0644]
startslip.tproj/Makefile.dist [new file with mode: 0644]
startslip.tproj/Makefile.preamble [new file with mode: 0644]
startslip.tproj/PB.project [new file with mode: 0644]
startslip.tproj/startslip.1 [new file with mode: 0644]
startslip.tproj/startslip.c [new file with mode: 0644]
stdethers.tproj/Makefile [new file with mode: 0644]
stdethers.tproj/Makefile.postamble [new file with mode: 0644]
stdethers.tproj/Makefile.preamble [new file with mode: 0644]
stdethers.tproj/PB.project [new file with mode: 0644]
stdethers.tproj/stdethers.8 [new file with mode: 0644]
stdethers.tproj/stdethers.c [new file with mode: 0644]
stdhosts.tproj/Makefile [new file with mode: 0644]
stdhosts.tproj/Makefile.postamble [new file with mode: 0644]
stdhosts.tproj/Makefile.preamble [new file with mode: 0644]
stdhosts.tproj/PB.project [new file with mode: 0644]
stdhosts.tproj/stdhosts.8 [new file with mode: 0644]
stdhosts.tproj/stdhosts.c [new file with mode: 0644]
syslogd.tproj/Makefile [new file with mode: 0644]
syslogd.tproj/Makefile.postamble [new file with mode: 0644]
syslogd.tproj/Makefile.preamble [new file with mode: 0644]
syslogd.tproj/PB.project [new file with mode: 0644]
syslogd.tproj/pathnames.h [new file with mode: 0644]
syslogd.tproj/syslog.conf.5 [new file with mode: 0644]
syslogd.tproj/syslogd.8 [new file with mode: 0644]
syslogd.tproj/syslogd.c [new file with mode: 0644]
talk.tproj/Makefile [new file with mode: 0644]
talk.tproj/Makefile.preamble [new file with mode: 0644]
talk.tproj/PB.project [new file with mode: 0644]
talk.tproj/ctl.c [new file with mode: 0644]
talk.tproj/ctl_transact.c [new file with mode: 0644]
talk.tproj/display.c [new file with mode: 0644]
talk.tproj/get_addrs.c [new file with mode: 0644]
talk.tproj/get_names.c [new file with mode: 0644]
talk.tproj/init_disp.c [new file with mode: 0644]
talk.tproj/invite.c [new file with mode: 0644]
talk.tproj/io.c [new file with mode: 0644]
talk.tproj/look_up.c [new file with mode: 0644]
talk.tproj/msgs.c [new file with mode: 0644]
talk.tproj/talk.1 [new file with mode: 0644]
talk.tproj/talk.c [new file with mode: 0644]
talk.tproj/talk.h [new file with mode: 0644]
talk.tproj/talk_ctl.h [new file with mode: 0644]
talkd.tproj/Makefile [new file with mode: 0644]
talkd.tproj/Makefile.dist [new file with mode: 0644]
talkd.tproj/Makefile.postamble [new file with mode: 0644]
talkd.tproj/Makefile.preamble [new file with mode: 0644]
talkd.tproj/PB.project [new file with mode: 0644]
talkd.tproj/announce.c [new file with mode: 0644]
talkd.tproj/print.c [new file with mode: 0644]
talkd.tproj/process.c [new file with mode: 0644]
talkd.tproj/table.c [new file with mode: 0644]
talkd.tproj/talkd.8 [new file with mode: 0644]
talkd.tproj/talkd.c [new file with mode: 0644]
talkd.tproj/talkd.h [new file with mode: 0644]
tcpdump.tproj/Makefile [new file with mode: 0644]
tcpdump.tproj/Makefile.postamble [new file with mode: 0644]
tcpdump.tproj/Makefile.preamble [new file with mode: 0644]
tcpdump.tproj/PB.project [new file with mode: 0644]
tcpdump.tproj/addrtoname.c [new file with mode: 0644]
tcpdump.tproj/addrtoname.h [new file with mode: 0644]
tcpdump.tproj/appletalk.h [new file with mode: 0644]
tcpdump.tproj/bootp.h [new file with mode: 0644]
tcpdump.tproj/bpf_dump.c [new file with mode: 0644]
tcpdump.tproj/decnet.h [new file with mode: 0644]
tcpdump.tproj/ethertype.h [new file with mode: 0644]
tcpdump.tproj/extract.h [new file with mode: 0644]
tcpdump.tproj/fddi.h [new file with mode: 0644]
tcpdump.tproj/gnuc.h [new file with mode: 0644]
tcpdump.tproj/igrp.h [new file with mode: 0644]
tcpdump.tproj/interface.h [new file with mode: 0644]
tcpdump.tproj/ipx.h [new file with mode: 0644]
tcpdump.tproj/llc.h [new file with mode: 0644]
tcpdump.tproj/machdep.c [new file with mode: 0644]
tcpdump.tproj/machdep.h [new file with mode: 0644]
tcpdump.tproj/mib.h [new file with mode: 0644]
tcpdump.tproj/netbios.h [new file with mode: 0644]
tcpdump.tproj/nfs.h [new file with mode: 0644]
tcpdump.tproj/nfsfh.h [new file with mode: 0644]
tcpdump.tproj/nfsv2.h [new file with mode: 0644]
tcpdump.tproj/ntp.h [new file with mode: 0644]
tcpdump.tproj/os-solaris2.h [new file with mode: 0644]
tcpdump.tproj/os-sunos4.h [new file with mode: 0644]
tcpdump.tproj/os-ultrix4.h [new file with mode: 0644]
tcpdump.tproj/ospf.h [new file with mode: 0644]
tcpdump.tproj/parsenfsfh.c [new file with mode: 0644]
tcpdump.tproj/print-arp.c [new file with mode: 0644]
tcpdump.tproj/print-atalk.c [new file with mode: 0644]
tcpdump.tproj/print-atm.c [new file with mode: 0644]
tcpdump.tproj/print-bootp.c [new file with mode: 0644]
tcpdump.tproj/print-decnet.c [new file with mode: 0644]
tcpdump.tproj/print-domain.c [new file with mode: 0644]
tcpdump.tproj/print-dvmrp.c [new file with mode: 0644]
tcpdump.tproj/print-egp.c [new file with mode: 0644]
tcpdump.tproj/print-ether.c [new file with mode: 0644]
tcpdump.tproj/print-fddi.c [new file with mode: 0644]
tcpdump.tproj/print-gre.c [new file with mode: 0644]
tcpdump.tproj/print-icmp.c [new file with mode: 0644]
tcpdump.tproj/print-igrp.c [new file with mode: 0644]
tcpdump.tproj/print-ip.c [new file with mode: 0644]
tcpdump.tproj/print-ipx.c [new file with mode: 0644]
tcpdump.tproj/print-isoclns.c [new file with mode: 0644]
tcpdump.tproj/print-krb.c [new file with mode: 0644]
tcpdump.tproj/print-llc.c [new file with mode: 0644]
tcpdump.tproj/print-netbios.c [new file with mode: 0644]
tcpdump.tproj/print-nfs.c [new file with mode: 0644]
tcpdump.tproj/print-ntp.c [new file with mode: 0644]
tcpdump.tproj/print-null.c [new file with mode: 0644]
tcpdump.tproj/print-ospf.c [new file with mode: 0644]
tcpdump.tproj/print-pim.c [new file with mode: 0644]
tcpdump.tproj/print-ppp.c [new file with mode: 0644]
tcpdump.tproj/print-rip.c [new file with mode: 0644]
tcpdump.tproj/print-skip.c [new file with mode: 0644]
tcpdump.tproj/print-sl.c [new file with mode: 0644]
tcpdump.tproj/print-snmp.c [new file with mode: 0644]
tcpdump.tproj/print-sunrpc.c [new file with mode: 0644]
tcpdump.tproj/print-tcp.c [new file with mode: 0644]
tcpdump.tproj/print-tftp.c [new file with mode: 0644]
tcpdump.tproj/print-udp.c [new file with mode: 0644]
tcpdump.tproj/print-wb.c [new file with mode: 0644]
tcpdump.tproj/strcasecmp.c [new file with mode: 0644]
tcpdump.tproj/tcpdump.c [new file with mode: 0644]
tcpdump.tproj/util.c [new file with mode: 0644]
tcpdump.tproj/version.c [new file with mode: 0644]
tcpdump.tproj/vfprintf.c [new file with mode: 0644]
telnet.tproj/Makefile [new file with mode: 0644]
telnet.tproj/Makefile.dist [new file with mode: 0644]
telnet.tproj/Makefile.preamble [new file with mode: 0644]
telnet.tproj/PB.project [new file with mode: 0644]
telnet.tproj/README [new file with mode: 0644]
telnet.tproj/authenc.c [new file with mode: 0644]
telnet.tproj/commands.c [new file with mode: 0644]
telnet.tproj/defines.h [new file with mode: 0644]
telnet.tproj/externs.h [new file with mode: 0644]
telnet.tproj/fdset.h [new file with mode: 0644]
telnet.tproj/general.h [new file with mode: 0644]
telnet.tproj/krb4-proto.h [new file with mode: 0644]
telnet.tproj/main.c [new file with mode: 0644]
telnet.tproj/network.c [new file with mode: 0644]
telnet.tproj/ring.c [new file with mode: 0644]
telnet.tproj/ring.h [new file with mode: 0644]
telnet.tproj/sys_bsd.c [new file with mode: 0644]
telnet.tproj/telnet.1 [new file with mode: 0644]
telnet.tproj/telnet.c [new file with mode: 0644]
telnet.tproj/terminal.c [new file with mode: 0644]
telnet.tproj/tn3270.c [new file with mode: 0644]
telnet.tproj/types.h [new file with mode: 0644]
telnet.tproj/utilities.c [new file with mode: 0644]
telnetd.tproj/Makefile [new file with mode: 0644]
telnetd.tproj/Makefile.postamble [new file with mode: 0644]
telnetd.tproj/Makefile.preamble [new file with mode: 0644]
telnetd.tproj/PB.project [new file with mode: 0644]
telnetd.tproj/authenc.c [new file with mode: 0644]
telnetd.tproj/defs.h [new file with mode: 0644]
telnetd.tproj/ext.h [new file with mode: 0644]
telnetd.tproj/global.c [new file with mode: 0644]
telnetd.tproj/pathnames.h [new file with mode: 0644]
telnetd.tproj/slc.c [new file with mode: 0644]
telnetd.tproj/state.c [new file with mode: 0644]
telnetd.tproj/sys_term.c [new file with mode: 0644]
telnetd.tproj/telnetd.8 [new file with mode: 0644]
telnetd.tproj/telnetd.c [new file with mode: 0644]
telnetd.tproj/telnetd.h [new file with mode: 0644]
telnetd.tproj/termstat.c [new file with mode: 0644]
telnetd.tproj/utility.c [new file with mode: 0644]
tftp.tproj/Makefile [new file with mode: 0644]
tftp.tproj/Makefile.preamble [new file with mode: 0644]
tftp.tproj/PB.project [new file with mode: 0644]
tftp.tproj/extern.h [new file with mode: 0644]
tftp.tproj/main.c [new file with mode: 0644]
tftp.tproj/tftp.1 [new file with mode: 0644]
tftp.tproj/tftp.c [new file with mode: 0644]
tftp.tproj/tftpsubs.c [new file with mode: 0644]
tftp.tproj/tftpsubs.h [new file with mode: 0644]
tftpd.tproj/Makefile [new file with mode: 0644]
tftpd.tproj/Makefile.postamble [new file with mode: 0644]
tftpd.tproj/Makefile.preamble [new file with mode: 0644]
tftpd.tproj/PB.project [new file with mode: 0644]
tftpd.tproj/tftpd.8 [new file with mode: 0644]
tftpd.tproj/tftpd.c [new file with mode: 0644]
timed.tproj/Makefile [new file with mode: 0644]
timed.tproj/Makefile.postamble [new file with mode: 0644]
timed.tproj/Makefile.preamble [new file with mode: 0644]
timed.tproj/PB.project [new file with mode: 0644]
timed.tproj/timed.tproj/Makefile [new file with mode: 0644]
timed.tproj/timed.tproj/Makefile.postamble [new file with mode: 0644]
timed.tproj/timed.tproj/Makefile.preamble [new file with mode: 0644]
timed.tproj/timed.tproj/PB.project [new file with mode: 0644]
timed.tproj/timed.tproj/acksend.c [new file with mode: 0644]
timed.tproj/timed.tproj/byteorder.c [new file with mode: 0644]
timed.tproj/timed.tproj/candidate.c [new file with mode: 0644]
timed.tproj/timed.tproj/cksum.c [new file with mode: 0644]
timed.tproj/timed.tproj/correct.c [new file with mode: 0644]
timed.tproj/timed.tproj/extern.h [new file with mode: 0644]
timed.tproj/timed.tproj/globals.h [new file with mode: 0644]
timed.tproj/timed.tproj/master.c [new file with mode: 0644]
timed.tproj/timed.tproj/measure.c [new file with mode: 0644]
timed.tproj/timed.tproj/networkdelta.c [new file with mode: 0644]
timed.tproj/timed.tproj/pathnames.h [new file with mode: 0644]
timed.tproj/timed.tproj/readmsg.c [new file with mode: 0644]
timed.tproj/timed.tproj/slave.c [new file with mode: 0644]
timed.tproj/timed.tproj/timed.8 [new file with mode: 0644]
timed.tproj/timed.tproj/timed.c [new file with mode: 0644]
timed.tproj/timedc.tproj/Makefile [new file with mode: 0644]
timed.tproj/timedc.tproj/Makefile.postamble [new file with mode: 0644]
timed.tproj/timedc.tproj/Makefile.preamble [new file with mode: 0644]
timed.tproj/timedc.tproj/PB.project [new file with mode: 0644]
timed.tproj/timedc.tproj/cmds.c [new file with mode: 0644]
timed.tproj/timedc.tproj/cmdtab.c [new file with mode: 0644]
timed.tproj/timedc.tproj/extern.h [new file with mode: 0644]
timed.tproj/timedc.tproj/h.template [new file with mode: 0644]
timed.tproj/timedc.tproj/m.template [new file with mode: 0644]
timed.tproj/timedc.tproj/timedc.c [new file with mode: 0644]
timed.tproj/timedc.tproj/timedc.h [new file with mode: 0644]
traceroute.tproj/Makefile [new file with mode: 0644]
traceroute.tproj/Makefile.postamble [new file with mode: 0644]
traceroute.tproj/Makefile.preamble [new file with mode: 0644]
traceroute.tproj/PB.project [new file with mode: 0644]
traceroute.tproj/README [new file with mode: 0644]
traceroute.tproj/mean.awk [new file with mode: 0644]
traceroute.tproj/median.awk [new file with mode: 0644]
traceroute.tproj/traceroute.8 [new file with mode: 0644]
traceroute.tproj/traceroute.c [new file with mode: 0644]
trpt.tproj/Makefile [new file with mode: 0644]
trpt.tproj/Makefile.postamble [new file with mode: 0644]
trpt.tproj/Makefile.preamble [new file with mode: 0644]
trpt.tproj/PB.project [new file with mode: 0644]
trpt.tproj/trpt.8 [new file with mode: 0644]
trpt.tproj/trpt.c [new file with mode: 0644]
trsp.tproj/Makefile [new file with mode: 0644]
trsp.tproj/Makefile.postamble [new file with mode: 0644]
trsp.tproj/Makefile.preamble [new file with mode: 0644]
trsp.tproj/PB.project [new file with mode: 0644]
trsp.tproj/trsp.8 [new file with mode: 0644]
trsp.tproj/trsp.c [new file with mode: 0644]
uucpd.tproj/Makefile [new file with mode: 0644]
uucpd.tproj/Makefile.postamble [new file with mode: 0644]
uucpd.tproj/Makefile.preamble [new file with mode: 0644]
uucpd.tproj/PB.project [new file with mode: 0644]
uucpd.tproj/pathnames.h [new file with mode: 0644]
uucpd.tproj/uucpd.c [new file with mode: 0644]
wall.tproj/Makefile [new file with mode: 0644]
wall.tproj/Makefile.dist [new file with mode: 0644]
wall.tproj/Makefile.postamble [new file with mode: 0644]
wall.tproj/Makefile.preamble [new file with mode: 0644]
wall.tproj/PB.project [new file with mode: 0644]
wall.tproj/ttymsg.c [new file with mode: 0644]
wall.tproj/wall.1 [new file with mode: 0644]
wall.tproj/wall.c [new file with mode: 0644]
ypbind.tproj/Makefile [new file with mode: 0644]
ypbind.tproj/Makefile.dist [new file with mode: 0644]
ypbind.tproj/Makefile.postamble [new file with mode: 0644]
ypbind.tproj/Makefile.preamble [new file with mode: 0644]
ypbind.tproj/PB.project [new file with mode: 0644]
ypbind.tproj/yp.x [new file with mode: 0644]
ypbind.tproj/ypbind.c [new file with mode: 0644]
ypcat.tproj/Makefile [new file with mode: 0644]
ypcat.tproj/Makefile.dist [new file with mode: 0644]
ypcat.tproj/Makefile.preamble [new file with mode: 0644]
ypcat.tproj/PB.project [new file with mode: 0644]
ypcat.tproj/ypcat.1 [new file with mode: 0644]
ypcat.tproj/ypcat.c [new file with mode: 0644]
ypinit.tproj/Makefile [new file with mode: 0644]
ypinit.tproj/Makefile.main [new file with mode: 0644]
ypinit.tproj/Makefile.yp [new file with mode: 0644]
ypinit.tproj/ypinit.sh [new file with mode: 0644]
ypmatch.tproj/Makefile [new file with mode: 0644]
ypmatch.tproj/Makefile.dist [new file with mode: 0644]
ypmatch.tproj/Makefile.preamble [new file with mode: 0644]
ypmatch.tproj/PB.project [new file with mode: 0644]
ypmatch.tproj/ypmatch.1 [new file with mode: 0644]
ypmatch.tproj/ypmatch.c [new file with mode: 0644]
yppoll.tproj/Makefile [new file with mode: 0644]
yppoll.tproj/Makefile.dist [new file with mode: 0644]
yppoll.tproj/Makefile.preamble [new file with mode: 0644]
yppoll.tproj/PB.project [new file with mode: 0644]
yppoll.tproj/yppoll.8 [new file with mode: 0644]
yppoll.tproj/yppoll.c [new file with mode: 0644]
yppush.tproj/Makefile [new file with mode: 0644]
yppush.tproj/Makefile.postamble [new file with mode: 0644]
yppush.tproj/Makefile.preamble [new file with mode: 0644]
yppush.tproj/PB.project [new file with mode: 0644]
yppush.tproj/ypdb.c [new file with mode: 0644]
yppush.tproj/ypdb.h [new file with mode: 0644]
yppush.tproj/ypdef.h [new file with mode: 0644]
yppush.tproj/yplib_host.c [new file with mode: 0644]
yppush.tproj/yplib_host.h [new file with mode: 0644]
yppush.tproj/yppush.8 [new file with mode: 0644]
yppush.tproj/yppush.c [new file with mode: 0644]
yppush.tproj/yppush.h [new file with mode: 0644]
yppush.tproj/yppush_err.c [new file with mode: 0644]
yppush.tproj/yppush_proc.c [new file with mode: 0644]
yppush.tproj/yppush_svc.c [new file with mode: 0644]
yppush.tproj/yppush_xdr.c [new file with mode: 0644]
ypserv.tproj/Makefile [new file with mode: 0644]
ypserv.tproj/Makefile.postamble [new file with mode: 0644]
ypserv.tproj/Makefile.preamble [new file with mode: 0644]
ypserv.tproj/PB.project [new file with mode: 0644]
ypserv.tproj/acl.c [new file with mode: 0644]
ypserv.tproj/acl.h [new file with mode: 0644]
ypserv.tproj/securenet [new file with mode: 0644]
ypserv.tproj/securenet.5 [new file with mode: 0644]
ypserv.tproj/yp.h [new file with mode: 0644]
ypserv.tproj/ypdb.c [new file with mode: 0644]
ypserv.tproj/ypdb.h [new file with mode: 0644]
ypserv.tproj/ypdef.h [new file with mode: 0644]
ypserv.tproj/yplog.c [new file with mode: 0644]
ypserv.tproj/yplog.h [new file with mode: 0644]
ypserv.tproj/ypserv.acl [new file with mode: 0644]
ypserv.tproj/ypserv.acl.5 [new file with mode: 0644]
ypserv.tproj/ypserv.c [new file with mode: 0644]
ypserv.tproj/ypserv_db.c [new file with mode: 0644]
ypserv.tproj/ypserv_proc.c [new file with mode: 0644]
ypserv.tproj/ypserv_xdr.c [new file with mode: 0644]
ypserv.tproj/ypserv_xdr_v1.c [new file with mode: 0644]
ypserv.tproj/ypv1.h [new file with mode: 0644]
ypset.tproj/Makefile [new file with mode: 0644]
ypset.tproj/Makefile.dist [new file with mode: 0644]
ypset.tproj/Makefile.preamble [new file with mode: 0644]
ypset.tproj/PB.project [new file with mode: 0644]
ypset.tproj/ypset.c [new file with mode: 0644]
ypwhich.tproj/Makefile [new file with mode: 0644]
ypwhich.tproj/Makefile.dist [new file with mode: 0644]
ypwhich.tproj/Makefile.preamble [new file with mode: 0644]
ypwhich.tproj/PB.project [new file with mode: 0644]
ypwhich.tproj/ypwhich.1 [new file with mode: 0644]
ypwhich.tproj/ypwhich.c [new file with mode: 0644]
ypxfr.tproj/Makefile [new file with mode: 0644]
ypxfr.tproj/Makefile.postamble [new file with mode: 0644]
ypxfr.tproj/Makefile.preamble [new file with mode: 0644]
ypxfr.tproj/PB.project [new file with mode: 0644]
ypxfr.tproj/ypdb.c [new file with mode: 0644]
ypxfr.tproj/ypdb.h [new file with mode: 0644]
ypxfr.tproj/ypdef.h [new file with mode: 0644]
ypxfr.tproj/yplib_host.c [new file with mode: 0644]
ypxfr.tproj/yplib_host.h [new file with mode: 0644]
ypxfr.tproj/yplog.c [new file with mode: 0644]
ypxfr.tproj/yplog.h [new file with mode: 0644]
ypxfr.tproj/ypxfr.8 [new file with mode: 0644]
ypxfr.tproj/ypxfr.c [new file with mode: 0644]
ypxfr.tproj/ypxfr_1perday.sh [new file with mode: 0755]
ypxfr.tproj/ypxfr_1perhour.sh [new file with mode: 0755]
ypxfr.tproj/ypxfr_2perday.sh [new file with mode: 0755]
ypxfr.tproj/ypxfr_xdr.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..b8719cd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,59 @@
+#
+# Generated by the Apple Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = network_cmds
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Aggregate
+
+SUBPROJECTS = timed.tproj bootparams
+
+TOOLS = arp.tproj domainname.tproj ftp.tproj ftpd.tproj identd.tproj\
+        ifconfig.tproj inetd.tproj logger.tproj netstat.tproj\
+        nfsd.tproj nfsiod.tproj nfsstat.tproj ping.tproj portmap.tproj\
+        rarpd.tproj rbootd.tproj rcp.tproj rexecd.tproj rlogin.tproj\
+        rlogind.tproj route.tproj routed.tproj rpcinfo.tproj rsh.tproj\
+        rshd.tproj ruptime.tproj rwho.tproj rwhod.tproj slattach.tproj\
+        sliplogin.tproj spray.tproj startslip.tproj syslogd.tproj\
+        talk.tproj talkd.tproj tcpdump.tproj telnet.tproj\
+        telnetd.tproj tftp.tproj tftpd.tproj traceroute.tproj\
+        trpt.tproj trsp.tproj uucpd.tproj wall.tproj ypbind.tproj\
+        ypcat.tproj ypmatch.tproj yppoll.tproj yppush.tproj\
+        ypserv.tproj ypset.tproj ypwhich.tproj ypxfr.tproj\
+        makedbm.tproj revnetgroup.tproj rpc_yppasswdd.tproj\
+        stdethers.tproj stdhosts.tproj natd.tproj ipfw.tproj
+
+LIBRARIES = alias pcap
+
+LEGACIES = newclient.tproj ypinit.tproj
+
+OTHERSRCS = Makefile Makefile.include Makefile.preamble
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = aggregate.make
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/Makefile.include b/Makefile.include
new file mode 100644 (file)
index 0000000..ee97aa2
--- /dev/null
@@ -0,0 +1,12 @@
+##
+## Temporary flags for static Teflon builds
+##
+
+#CODE_GEN_STYLE = STATIC
+#OTHER_LDFLAGS = -nostdlib /lib/crt0.o -L/tmp/lennart/lib -L/usr/local/lib
+#OTHER_LIBS = -linfo -lc -lm
+
+#OTHER_LDFLAGS = -nostdlib /lib/crt1.o
+#OTHER_LIBS = -framework System
+
+CHFLAGS = true         # until we really have chflags on our system
diff --git a/Makefile.preamble b/Makefile.preamble
new file mode 100644 (file)
index 0000000..a6b1e76
--- /dev/null
@@ -0,0 +1 @@
+CLEAN_ALL_SUBPROJECTS = YES
diff --git a/PB.project b/PB.project
new file mode 100644 (file)
index 0000000..3015bd3
--- /dev/null
@@ -0,0 +1,82 @@
+{
+    FILESTABLE = {
+        OTHER_SOURCES = (Makefile, Makefile.include, Makefile.preamble); 
+        SUBPROJECTS = (
+            alias, 
+            pcap, 
+            timed.tproj, 
+            arp.tproj, 
+            bootparams, 
+            domainname.tproj, 
+            ftp.tproj, 
+            ftpd.tproj, 
+            identd.tproj, 
+            ifconfig.tproj, 
+            inetd.tproj, 
+            logger.tproj, 
+            netstat.tproj, 
+            newclient.tproj, 
+            nfsd.tproj, 
+            nfsiod.tproj, 
+            nfsstat.tproj, 
+            ping.tproj, 
+            portmap.tproj, 
+            rarpd.tproj, 
+            rbootd.tproj, 
+            rcp.tproj, 
+            rexecd.tproj, 
+            rlogin.tproj, 
+            rlogind.tproj, 
+            route.tproj, 
+            routed.tproj, 
+            rpcinfo.tproj, 
+            rsh.tproj, 
+            rshd.tproj, 
+            ruptime.tproj, 
+            rwho.tproj, 
+            rwhod.tproj, 
+            slattach.tproj, 
+            sliplogin.tproj, 
+            spray.tproj, 
+            startslip.tproj, 
+            syslogd.tproj, 
+            talk.tproj, 
+            talkd.tproj, 
+            tcpdump.tproj, 
+            telnet.tproj, 
+            telnetd.tproj, 
+            tftp.tproj, 
+            tftpd.tproj, 
+            traceroute.tproj, 
+            trpt.tproj, 
+            trsp.tproj, 
+            uucpd.tproj, 
+            wall.tproj, 
+            ypbind.tproj, 
+            ypcat.tproj, 
+            ypinit.tproj, 
+            ypmatch.tproj, 
+            yppoll.tproj, 
+            yppush.tproj, 
+            ypserv.tproj, 
+            ypset.tproj, 
+            ypwhich.tproj, 
+            ypxfr.tproj, 
+            makedbm.tproj, 
+            revnetgroup.tproj, 
+            rpc_yppasswdd.tproj, 
+            stdethers.tproj, 
+            stdhosts.tproj, 
+            natd.tproj, 
+            ipfw.tproj
+        ); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PROJECTNAME = network_cmds; 
+    PROJECTTYPE = Aggregate; 
+    PROJECTVERSION = 2.8; 
+}
diff --git a/alias/Makefile b/alias/Makefile
new file mode 100644 (file)
index 0000000..f844cc3
--- /dev/null
@@ -0,0 +1,59 @@
+#
+# Generated by the Apple Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = alias
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Library
+
+HFILES = alias.h alias_local.h
+
+CFILES = alias.c alias_cuseeme.c alias_db.c alias_ftp.c alias_irc.c\
+         alias_nbt.c alias_proxy.c alias_util.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CURRENTLY_ACTIVE_VERSION = YES
+DEPLOY_WITH_VERSION_NAME = A
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = library.make
+NEXTSTEP_INSTALLDIR = /usr/lib
+WINDOWS_INSTALLDIR = /Developer/Libraries
+PDO_UNIX_INSTALLDIR = /usr/lib
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+PROJECT_HEADERS = alias.h
+
+
+
+WINDOWS_PUBLIC_HEADERS_DIR = /Developer/Headers/$(NAME)
+
+PDO_UNIX_PUBLIC_HEADERS_DIR = /Developer/Headers/$(NAME)
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/alias/Makefile.postamble b/alias/Makefile.postamble
new file mode 100644 (file)
index 0000000..411cde6
--- /dev/null
@@ -0,0 +1,100 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/alias/Makefile.preamble b/alias/Makefile.preamble
new file mode 100644 (file)
index 0000000..f02898c
--- /dev/null
@@ -0,0 +1,138 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+OTHER_LDFLAGS += -seg1addr 0xf9300000
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+DSTROOT = $(HOME)
diff --git a/alias/PB.project b/alias/PB.project
new file mode 100644 (file)
index 0000000..e87cc27
--- /dev/null
@@ -0,0 +1,39 @@
+{
+    CURRENTLY_ACTIVE_VERSION = YES; 
+    DEPLOY_WITH_VERSION_NAME = A; 
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        H_FILES = (alias.h, alias_local.h); 
+        OTHER_LINKED = (
+            alias.c, 
+            alias_cuseeme.c, 
+            alias_db.c, 
+            alias_ftp.c, 
+            alias_irc.c, 
+            alias_nbt.c, 
+            alias_proxy.c, 
+            alias_util.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        PROJECT_HEADERS = (alias.h); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/lib; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_INSTALLDIR = /usr/lib; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PDO_UNIX_PUBLICHEADERSDIR = "/Developer/Headers/$(NAME)"; 
+    PROJECTNAME = alias; 
+    PROJECTTYPE = Library; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = /Developer/Libraries; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+    WINDOWS_PUBLICHEADERSDIR = "/Developer/Headers/$(NAME)"; 
+}
diff --git a/alias/alias.c b/alias/alias.c
new file mode 100644 (file)
index 0000000..10e0ccc
--- /dev/null
@@ -0,0 +1,1318 @@
+/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */
+/*
+    Alias.c provides supervisory control for the functions of the
+    packet aliasing software.  It consists of routines to monitor
+    TCP connection state, protocol-specific aliasing routines,
+    fragment handling and the following outside world functional
+    interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn,
+    PacketAliasIn and PacketAliasOut.
+
+    The other C program files are briefly described. The data
+    structure framework which holds information needed to translate
+    packets is encapsulated in alias_db.c.  Data is accessed by
+    function calls, so other segments of the program need not know
+    about the underlying data structures.  Alias_ftp.c contains
+    special code for modifying the ftp PORT command used to establish
+    data connections, while alias_irc.c do the same for IRC
+    DCC. Alias_util.c contains a few utility routines.
+
+    This software is placed into the public domain with no restrictions
+    on its distribution.
+
+    Version 1.0 August, 1996  (cjm)
+
+    Version 1.1 August 20, 1996  (cjm)
+        PPP host accepts incoming connections for ports 0 to 1023.
+        (Gary Roberts pointed out the need to handle incoming
+         connections.)
+
+    Version 1.2 September 7, 1996 (cjm)
+        Fragment handling error in alias_db.c corrected.
+        (Tom Torrance helped fix this problem.)
+
+    Version 1.4 September 16, 1996 (cjm)
+        - A more generalized method for handling incoming
+          connections, without the 0-1023 restriction, is
+          implemented in alias_db.c
+        - Improved ICMP support in alias.c.  Traceroute
+          packet streams can now be correctly aliased.
+        - TCP connection closing logic simplified in
+          alias.c and now allows for additional 1 minute
+          "grace period" after FIN or RST is observed.
+
+    Version 1.5 September 17, 1996 (cjm)
+        Corrected error in handling incoming UDP packets with 0 checksum.
+        (Tom Torrance helped fix this problem.)
+
+    Version 1.6 September 18, 1996 (cjm)
+        Simplified ICMP aliasing scheme.  Should now support
+        traceroute from Win95 as well as FreeBSD.
+
+    Version 1.7 January 9, 1997 (cjm)
+        - Out-of-order fragment handling.
+        - IP checksum error fixed for ftp transfers
+          from aliasing host.
+        - Integer return codes added to all
+          aliasing/de-aliasing functions.
+        - Some obsolete comments cleaned up.
+        - Differential checksum computations for
+          IP header (TCP, UDP and ICMP were already
+          differential).
+
+    Version 2.1 May 1997 (cjm)
+        - Added support for outgoing ICMP error
+          messages.
+        - Added two functions PacketAliasIn2()
+          and PacketAliasOut2() for dynamic address
+          control (e.g. round-robin allocation of
+          incoming packets).
+
+    Version 2.2 July 1997 (cjm)
+        - Rationalized API function names to begin
+          with "PacketAlias..."
+        - Eliminated PacketAliasIn2() and
+          PacketAliasOut2() as poorly conceived.
+
+    Version 2.3 Dec 1998 (dillon)
+       - Major bounds checking additions, see FreeBSD/CVS
+
+    See HISTORY file for additional revisions.
+
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#ifndef IPPROTO_GRE
+#define IPPROTO_GRE 47
+#endif
+
+#include "alias_local.h"
+#include "alias.h"
+
+#define NETBIOS_NS_PORT_NUMBER 137
+#define NETBIOS_DGM_PORT_NUMBER 138
+#define FTP_CONTROL_PORT_NUMBER 21
+#define IRC_CONTROL_PORT_NUMBER_1 6667
+#define IRC_CONTROL_PORT_NUMBER_2 6668
+#define CUSEEME_PORT_NUMBER 7648
+
+
+
+
+/* TCP Handling Routines
+
+    TcpMonitorIn()  -- These routines monitor TCP connections, and
+    TcpMonitorOut()    delete a link when a connection is closed.
+
+These routines look for SYN, ACK and RST flags to determine when TCP
+connections open and close.  When a TCP connection closes, the data
+structure containing packet aliasing information is deleted after
+a timeout period.
+*/
+
+/* Local prototypes */
+static void TcpMonitorIn(struct ip *, struct alias_link *);
+
+static void TcpMonitorOut(struct ip *, struct alias_link *);
+
+
+static void
+TcpMonitorIn(struct ip *pip, struct alias_link *link)
+{
+    struct tcphdr *tc;
+
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+    switch (GetStateIn(link))
+    {
+        case ALIAS_TCP_STATE_NOT_CONNECTED:
+            if (tc->th_flags & TH_SYN)
+                SetStateIn(link, ALIAS_TCP_STATE_CONNECTED);
+            break;
+        case ALIAS_TCP_STATE_CONNECTED:
+            if (tc->th_flags & TH_FIN
+                || tc->th_flags & TH_RST)
+                SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED);
+            break;
+    }
+}
+
+static void
+TcpMonitorOut(struct ip *pip, struct alias_link *link)
+{
+    struct tcphdr *tc;
+
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+     
+    switch (GetStateOut(link))
+    {
+        case ALIAS_TCP_STATE_NOT_CONNECTED:
+            if (tc->th_flags & TH_SYN)
+                SetStateOut(link, ALIAS_TCP_STATE_CONNECTED);
+            break;
+        case ALIAS_TCP_STATE_CONNECTED:
+            if (tc->th_flags & TH_FIN
+                || tc->th_flags & TH_RST)
+                SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED);
+            break;
+    }
+}
+
+
+
+
+
+/* Protocol Specific Packet Aliasing Routines 
+
+    IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2(), IcmpAliasIn3()
+    IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2(), IcmpAliasOut3()
+    UdpAliasIn(), UdpAliasOut()
+    TcpAliasIn(), TcpAliasOut()
+
+These routines handle protocol specific details of packet aliasing.
+One may observe a certain amount of repetitive arithmetic in these
+functions, the purpose of which is to compute a revised checksum
+without actually summing over the entire data packet, which could be
+unnecessarily time consuming.
+
+The purpose of the packet aliasing routines is to replace the source
+address of the outgoing packet and then correctly put it back for
+any incoming packets.  For TCP and UDP, ports are also re-mapped.
+
+For ICMP echo/timestamp requests and replies, the following scheme
+is used: the id number is replaced by an alias for the outgoing
+packet.
+
+ICMP error messages are handled by looking at the IP fragment
+in the data section of the message.
+
+For TCP and UDP protocols, a port number is chosen for an outgoing
+packet, and then incoming packets are identified by IP address and
+port numbers.  For TCP packets, there is additional logic in the event
+that sequence and ack numbers have been altered (as is the case for
+FTP data port commands).
+
+The port numbers used by the packet aliasing module are not true
+ports in the Unix sense.  No sockets are actually bound to ports.
+They are more correctly thought of as placeholders.
+
+All packets go through the aliasing mechanism, whether they come from
+the gateway machine or other machines on a local area network.
+*/
+
+
+/* Local prototypes */
+static int IcmpAliasIn1(struct ip *);
+static int IcmpAliasIn2(struct ip *);
+static int IcmpAliasIn3(struct ip *);
+static int IcmpAliasIn (struct ip *);
+
+static int IcmpAliasOut1(struct ip *);
+static int IcmpAliasOut2(struct ip *);
+static int IcmpAliasOut3(struct ip *);
+static int IcmpAliasOut (struct ip *);
+
+static int UdpAliasOut(struct ip *);
+static int UdpAliasIn (struct ip *);
+
+static int TcpAliasOut(struct ip *, int);
+static int TcpAliasIn (struct ip *);
+
+
+static int
+IcmpAliasIn1(struct ip *pip)
+{
+/*
+    De-alias incoming echo and timestamp replies
+*/
+    struct alias_link *link;
+    struct icmp *ic;
+
+    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+/* Get source address from ICMP data field and restore original data */
+    link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id);
+    if (link != NULL)
+    {
+        u_short original_id;
+        int accumulate;
+
+        original_id = GetOriginalPort(link);
+
+/* Adjust ICMP checksum */
+        accumulate  = ic->icmp_id;
+        accumulate -= original_id;
+        ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Put original sequence number back in */
+        ic->icmp_id = original_id;
+
+/* Put original address back into IP header */
+        {
+            struct in_addr original_address;
+
+            original_address = GetOriginalAddress(link);
+            DifferentialChecksum(&pip->ip_sum,
+                                 (u_short *) &original_address,
+                                 (u_short *) &pip->ip_dst,
+                                 2);
+            pip->ip_dst = original_address;
+        }
+
+        return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_IGNORED);
+}
+
+static int
+IcmpAliasIn2(struct ip *pip)
+{
+/*
+    Alias incoming ICMP error messages containing
+    IP header and first 64 bits of datagram.
+*/
+    struct ip *ip;
+    struct icmp *ic, *ic2;
+    struct udphdr *ud;
+    struct tcphdr *tc;
+    struct alias_link *link;
+
+    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+    ip = (struct ip *) ic->icmp_data;
+
+    ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2));
+    tc = (struct tcphdr *) ud;
+    ic2 = (struct icmp *) ud;
+
+    if (ip->ip_p == IPPROTO_UDP)
+        link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
+                            ud->uh_dport, ud->uh_sport,
+                            IPPROTO_UDP);
+    else if (ip->ip_p == IPPROTO_TCP)
+        link = FindUdpTcpIn(ip->ip_dst, ip->ip_src,
+                            tc->th_dport, tc->th_sport,
+                            IPPROTO_TCP);
+    else if (ip->ip_p == IPPROTO_ICMP) {
+        if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP)
+            link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id);
+         else
+            link = NULL;
+    } else
+        link = NULL;
+
+    if (link != NULL)
+    {
+        if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP)
+        {
+            u_short *sptr;
+            int accumulate;
+            struct in_addr original_address;
+            u_short original_port;
+
+            original_address = GetOriginalAddress(link);
+            original_port = GetOriginalPort(link);
+    
+/* Adjust ICMP checksum */
+            sptr = (u_short *) &(ip->ip_src);
+            accumulate  = *sptr++;
+            accumulate += *sptr;
+            sptr = (u_short *) &original_address;
+            accumulate -= *sptr++;
+            accumulate -= *sptr;
+            accumulate += ud->uh_sport;
+            accumulate -= original_port;
+            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Un-alias address in IP header */
+            DifferentialChecksum(&pip->ip_sum,
+                                 (u_short *) &original_address,
+                                 (u_short *) &pip->ip_dst,
+                                 2);
+            pip->ip_dst = original_address;
+
+/* Un-alias address and port number of original IP packet
+fragment contained in ICMP data section */
+            ip->ip_src = original_address;
+            ud->uh_sport = original_port; 
+        }
+        else if (pip->ip_p == IPPROTO_ICMP)
+        {
+            u_short *sptr;
+            int accumulate;
+            struct in_addr original_address;
+            u_short original_id;
+
+            original_address = GetOriginalAddress(link);
+            original_id = GetOriginalPort(link);
+
+/* Adjust ICMP checksum */
+            sptr = (u_short *) &(ip->ip_src);
+            accumulate  = *sptr++;
+            accumulate += *sptr;
+            sptr = (u_short *) &original_address;
+            accumulate -= *sptr++;
+            accumulate -= *sptr;
+            accumulate += ic2->icmp_id;
+            accumulate -= original_id;
+            ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Un-alias address in IP header */
+            DifferentialChecksum(&pip->ip_sum,
+                                 (u_short *) &original_address,
+                                 (u_short *) &pip->ip_dst,
+                                 2);
+            pip->ip_dst = original_address;
+
+/* Un-alias address of original IP packet and seqence number of 
+   embedded icmp datagram */
+            ip->ip_src = original_address;
+            ic2->icmp_id = original_id;
+        }
+        return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_IGNORED);
+}
+
+static int
+IcmpAliasIn3(struct ip *pip)
+{
+    struct in_addr original_address;
+
+    original_address = FindOriginalAddress(pip->ip_dst);
+    DifferentialChecksum(&pip->ip_sum,
+                         (u_short *) &original_address,
+                         (u_short *) &pip->ip_dst,
+                         2);
+    pip->ip_dst = original_address;
+
+    return PKT_ALIAS_OK;
+}
+
+
+static int
+IcmpAliasIn(struct ip *pip)
+{
+    int iresult;
+    struct icmp *ic;
+
+/* Return if proxy-only mode is enabled */
+    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+        return PKT_ALIAS_OK;
+
+    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+    iresult = PKT_ALIAS_IGNORED;
+    switch (ic->icmp_type)
+    {
+        case ICMP_ECHOREPLY:
+        case ICMP_TSTAMPREPLY:
+            if (ic->icmp_code == 0)
+            {
+                iresult = IcmpAliasIn1(pip);
+            }
+            break;
+        case ICMP_UNREACH:
+        case ICMP_SOURCEQUENCH:
+        case ICMP_TIMXCEED:
+        case ICMP_PARAMPROB:
+            iresult = IcmpAliasIn2(pip);
+            break;
+        case ICMP_ECHO:
+        case ICMP_TSTAMP:
+            iresult = IcmpAliasIn3(pip);
+            break;
+    }
+    return(iresult);
+}
+
+
+static int
+IcmpAliasOut1(struct ip *pip)
+{
+/*
+    Alias ICMP echo and timestamp packets
+*/
+    struct alias_link *link;
+    struct icmp *ic;
+
+    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+/* Save overwritten data for when echo packet returns */
+    link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id);
+    if (link != NULL)
+    {
+        u_short alias_id;
+        int accumulate;
+
+        alias_id = GetAliasPort(link);
+
+/* Since data field is being modified, adjust ICMP checksum */
+        accumulate  = ic->icmp_id;
+        accumulate -= alias_id;
+        ADJUST_CHECKSUM(accumulate, ic->icmp_cksum)
+
+/* Alias sequence number */
+        ic->icmp_id = alias_id;
+
+/* Change source address */
+        {
+            struct in_addr alias_address;
+
+            alias_address = GetAliasAddress(link);
+            DifferentialChecksum(&pip->ip_sum,
+                                 (u_short *) &alias_address,
+                                 (u_short *) &pip->ip_src,
+                                 2);
+            pip->ip_src = alias_address;
+        }
+
+        return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_IGNORED);
+}
+
+
+static int
+IcmpAliasOut2(struct ip *pip)
+{
+/*
+    Alias outgoing ICMP error messages containing
+    IP header and first 64 bits of datagram.
+*/
+    struct in_addr alias_addr;
+    struct ip *ip;
+    struct icmp *ic;
+
+    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+    ip = (struct ip *) ic->icmp_data;
+
+    alias_addr = FindAliasAddress(ip->ip_src);
+
+/* Alias destination address in IP fragment */
+    DifferentialChecksum(&ic->icmp_cksum,
+                         (u_short *) &alias_addr,
+                         (u_short *) &ip->ip_dst,
+                         2);
+    ip->ip_dst = alias_addr;
+
+/* alias source address in IP header */
+    DifferentialChecksum(&pip->ip_sum,
+                         (u_short *) &alias_addr,
+                         (u_short *) &pip->ip_src,
+                         2);
+    pip->ip_src = alias_addr;
+
+    return PKT_ALIAS_OK;
+}
+
+
+static int
+IcmpAliasOut3(struct ip *pip)
+{
+/*
+  Handle outgoing echo and timestamp replies.  The
+  only thing which is done in this case is to alias
+  the source IP address of the packet.
+*/
+    struct in_addr alias_addr;
+
+    alias_addr = FindAliasAddress(pip->ip_src);
+    DifferentialChecksum(&pip->ip_sum,
+                         (u_short *) &alias_addr,
+                         (u_short *) &pip->ip_src,
+                         2);
+    pip->ip_src = alias_addr;
+
+    return PKT_ALIAS_OK;
+}
+
+
+static int
+IcmpAliasOut(struct ip *pip)
+{
+    int iresult;
+    struct icmp *ic;
+
+/* Return if proxy-only mode is enabled */
+    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+        return PKT_ALIAS_OK;
+
+    ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2));
+
+    iresult = PKT_ALIAS_IGNORED;
+    switch (ic->icmp_type)
+    {
+        case ICMP_ECHO:
+        case ICMP_TSTAMP:
+            if (ic->icmp_code == 0)
+            {
+                iresult = IcmpAliasOut1(pip);
+            }
+            break;
+        case ICMP_UNREACH:
+        case ICMP_SOURCEQUENCH:
+        case ICMP_TIMXCEED:
+        case ICMP_PARAMPROB:
+            iresult = IcmpAliasOut2(pip);
+            break;
+        case ICMP_ECHOREPLY:
+        case ICMP_TSTAMPREPLY:
+            iresult = IcmpAliasOut3(pip);
+    }
+    return(iresult);
+}
+
+
+
+static int
+PptpAliasIn(struct ip *pip)
+{
+/*
+  Handle incoming PPTP packets. The
+  only thing which is done in this case is to alias
+  the dest IP address of the packet to our inside
+  machine.
+*/
+    struct in_addr alias_addr;
+
+    if (!GetPptpAlias (&alias_addr))
+       return PKT_ALIAS_IGNORED;
+
+    if (pip->ip_src.s_addr != alias_addr.s_addr) {
+
+           DifferentialChecksum(&pip->ip_sum,
+                                (u_short *) &alias_addr,
+                                (u_short *) &pip->ip_dst,
+                                2);
+           pip->ip_dst = alias_addr;
+    }
+
+    return PKT_ALIAS_OK;
+}
+
+
+static int
+PptpAliasOut(struct ip *pip)
+{
+/*
+  Handle outgoing PPTP packets. The
+  only thing which is done in this case is to alias
+  the source IP address of the packet.
+*/
+    struct in_addr alias_addr;
+
+    if (!GetPptpAlias (&alias_addr))
+       return PKT_ALIAS_IGNORED;
+
+    if (pip->ip_src.s_addr == alias_addr.s_addr) {
+
+           alias_addr = FindAliasAddress(pip->ip_src);
+           DifferentialChecksum(&pip->ip_sum,
+                                (u_short *) &alias_addr,
+                                (u_short *) &pip->ip_src,
+                                2);
+           pip->ip_src = alias_addr;
+    }
+
+    return PKT_ALIAS_OK;
+}
+
+
+
+static int
+UdpAliasIn(struct ip *pip)
+{
+    struct udphdr *ud;
+    struct alias_link *link;
+
+/* Return if proxy-only mode is enabled */
+    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+        return PKT_ALIAS_OK;
+
+    ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+    link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
+                        ud->uh_sport, ud->uh_dport,
+                        IPPROTO_UDP);
+    if (link != NULL)
+    {
+        struct in_addr alias_address;
+        struct in_addr original_address;
+        u_short alias_port;
+        int accumulate;
+        u_short *sptr;
+       int r = 0;
+
+        alias_address = GetAliasAddress(link);
+        original_address = GetOriginalAddress(link);
+        alias_port = ud->uh_dport;
+        ud->uh_dport = GetOriginalPort(link);
+
+/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
+               if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
+         || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
+               {
+            r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
+               } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
+         || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
+               {
+            r = AliasHandleUdpNbtNS(pip, link, 
+                                                               &alias_address,
+                                                               &alias_port,
+                                                               &original_address, 
+                                                               &ud->uh_dport );
+               }
+
+        if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
+            AliasHandleCUSeeMeIn(pip, original_address);
+
+/* If UDP checksum is not zero, then adjust since destination port */
+/* is being unaliased and destination port is being altered.       */
+        if (ud->uh_sum != 0)
+        {
+            accumulate  = alias_port;
+            accumulate -= ud->uh_dport;
+            sptr = (u_short *) &alias_address;
+            accumulate += *sptr++;
+            accumulate += *sptr;
+            sptr = (u_short *) &original_address;
+            accumulate -= *sptr++;
+            accumulate -= *sptr;
+            ADJUST_CHECKSUM(accumulate, ud->uh_sum)
+        }
+
+/* Restore original IP address */
+        DifferentialChecksum(&pip->ip_sum,
+                             (u_short *) &original_address,
+                             (u_short *) &pip->ip_dst,
+                             2);
+        pip->ip_dst = original_address;
+
+       /*
+        * If we cannot figure out the packet, ignore it.
+        */
+       if (r < 0)
+           return(PKT_ALIAS_IGNORED);
+       else
+           return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_IGNORED);
+}
+
+static int
+UdpAliasOut(struct ip *pip)
+{
+    struct udphdr *ud;
+    struct alias_link *link;
+
+/* Return if proxy-only mode is enabled */
+    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+        return PKT_ALIAS_OK;
+
+    ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+    link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
+                         ud->uh_sport, ud->uh_dport,
+                         IPPROTO_UDP);
+    if (link != NULL)
+    {
+        u_short alias_port;
+        struct in_addr alias_address;
+
+        alias_address = GetAliasAddress(link);
+        alias_port = GetAliasPort(link);
+
+        if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
+            AliasHandleCUSeeMeOut(pip, link);
+
+/* If NETBIOS Datagram, It should be alias address in UDP Data, too */
+               if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
+         || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
+               {
+            AliasHandleUdpNbt(pip, link, &alias_address, alias_port);
+               } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
+         || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
+               {
+            AliasHandleUdpNbtNS(pip, link,
+                                                               &pip->ip_src,
+                                                               &ud->uh_sport,
+                                                           &alias_address,
+                                                               &alias_port); 
+               }
+
+/* If UDP checksum is not zero, adjust since source port is */
+/* being aliased and source address is being altered        */
+        if (ud->uh_sum != 0)
+        {
+            int accumulate;
+            u_short *sptr;
+
+            accumulate  = ud->uh_sport;
+            accumulate -= alias_port;
+            sptr = (u_short *) &(pip->ip_src);
+            accumulate += *sptr++;
+            accumulate += *sptr;
+            sptr = (u_short *) &alias_address;
+            accumulate -= *sptr++;
+            accumulate -= *sptr;
+            ADJUST_CHECKSUM(accumulate, ud->uh_sum)
+        }
+
+/* Put alias port in UDP header */
+        ud->uh_sport = alias_port;
+
+/* Change source address */
+        DifferentialChecksum(&pip->ip_sum,
+                             (u_short *) &alias_address,
+                             (u_short *) &pip->ip_src,
+                             2);
+        pip->ip_src = alias_address;
+
+        return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_IGNORED);
+}
+
+
+
+static int
+TcpAliasIn(struct ip *pip)
+{
+    struct tcphdr *tc;
+    struct alias_link *link;
+
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+    link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
+                        tc->th_sport, tc->th_dport,
+                        IPPROTO_TCP);
+    if (link != NULL)
+    {
+        struct in_addr alias_address;
+        struct in_addr original_address;
+        struct in_addr proxy_address;
+        u_short alias_port;
+        u_short proxy_port;
+        int accumulate;
+        u_short *sptr;
+
+        alias_address = GetAliasAddress(link);
+        original_address = GetOriginalAddress(link);
+        proxy_address = GetProxyAddress(link);
+        alias_port = tc->th_dport;
+        tc->th_dport = GetOriginalPort(link);
+        proxy_port = GetProxyPort(link);
+
+/* Adjust TCP checksum since destination port is being unaliased */
+/* and destination port is being altered.                        */
+        accumulate  = alias_port;
+        accumulate -= tc->th_dport;
+        sptr = (u_short *) &alias_address;
+        accumulate += *sptr++;
+        accumulate += *sptr;
+        sptr = (u_short *) &original_address;
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+/* If this is a proxy, then modify the tcp source port  and
+   checksum accumulation */
+        if (proxy_port != 0)
+        {
+            accumulate += tc->th_sport;
+            tc->th_sport = proxy_port;
+            accumulate -= tc->th_sport;
+
+            sptr = (u_short *) &pip->ip_src;
+            accumulate += *sptr++;
+            accumulate += *sptr;
+            sptr = (u_short *) &proxy_address;
+            accumulate -= *sptr++;
+            accumulate -= *sptr;
+        }
+
+/* See if ack number needs to be modified */
+        if (GetAckModified(link) == 1)
+        {
+            int delta;
+
+            delta = GetDeltaAckIn(pip, link);
+            if (delta != 0)
+            {
+                sptr = (u_short *) &tc->th_ack;
+                accumulate += *sptr++;
+                accumulate += *sptr;
+                tc->th_ack = htonl(ntohl(tc->th_ack) - delta);
+                sptr = (u_short *) &tc->th_ack;
+                accumulate -= *sptr++;
+                accumulate -= *sptr;
+            }
+        }
+
+        ADJUST_CHECKSUM(accumulate, tc->th_sum);
+
+/* Restore original IP address */
+        sptr = (u_short *) &pip->ip_dst;
+        accumulate  = *sptr++;
+        accumulate += *sptr;
+        pip->ip_dst = original_address;
+        sptr = (u_short *) &pip->ip_dst;
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+/* If this is a transparent proxy packet, then modify the source
+   address */
+        if (proxy_address.s_addr != 0)
+        {
+            sptr = (u_short *) &pip->ip_src;
+            accumulate += *sptr++;
+            accumulate += *sptr;
+            pip->ip_src = proxy_address;
+            sptr = (u_short *) &pip->ip_src;
+            accumulate -= *sptr++;
+            accumulate -= *sptr;
+        }
+
+        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
+
+/* Monitor TCP connection state */
+        TcpMonitorIn(pip, link);
+
+        return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_IGNORED);
+}
+
+static int
+TcpAliasOut(struct ip *pip, int maxpacketsize)
+{
+    int proxy_type;
+    u_short dest_port;
+    u_short proxy_server_port;
+    struct in_addr dest_address;
+    struct in_addr proxy_server_address;
+    struct tcphdr *tc;
+    struct alias_link *link;
+
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+    proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
+
+    if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
+        return PKT_ALIAS_OK;
+
+/* If this is a transparent proxy, save original destination,
+   then alter the destination and adust checksums */
+    dest_port = tc->th_dport;
+    dest_address = pip->ip_dst;
+    if (proxy_type != 0)
+    {
+        int accumulate;
+        u_short *sptr;
+
+        accumulate = tc->th_dport;
+        tc->th_dport = proxy_server_port;
+        accumulate -= tc->th_dport;
+
+        sptr = (u_short *) &(pip->ip_dst);
+        accumulate += *sptr++;
+        accumulate += *sptr;
+        sptr = (u_short *) &proxy_server_address;
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+        ADJUST_CHECKSUM(accumulate, tc->th_sum);
+
+        sptr = (u_short *) &(pip->ip_dst);
+        accumulate  = *sptr++;
+        accumulate += *sptr;
+        pip->ip_dst = proxy_server_address;
+        sptr = (u_short *) &(pip->ip_dst);
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
+    }
+
+    link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
+                         tc->th_sport, tc->th_dport,
+                         IPPROTO_TCP);
+    if (link !=NULL)
+    {
+        u_short alias_port;
+        struct in_addr alias_address;
+        int accumulate;
+        u_short *sptr;
+
+/* Save original destination address, if this is a proxy packet.
+   Also modify packet to include destination encoding. */
+        if (proxy_type != 0)
+        {
+            SetProxyPort(link, dest_port);
+            SetProxyAddress(link, dest_address);
+            ProxyModify(link, pip, maxpacketsize, proxy_type);
+        }
+
+/* Get alias address and port */
+        alias_port = GetAliasPort(link);
+        alias_address = GetAliasAddress(link);
+
+/* Monitor tcp connection state */
+        TcpMonitorOut(pip, link);
+
+/* Special processing for IP encoding protocols */
+        if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
+         || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
+            AliasHandleFtpOut(pip, link, maxpacketsize);
+        if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
+         || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
+            AliasHandleIrcOut(pip, link, maxpacketsize);
+
+/* Adjust TCP checksum since source port is being aliased */
+/* and source address is being altered                    */
+        accumulate  = tc->th_sport;
+        tc->th_sport = alias_port;
+        accumulate -= tc->th_sport;
+
+        sptr = (u_short *) &(pip->ip_src);
+        accumulate += *sptr++;
+        accumulate += *sptr;
+        sptr = (u_short *) &alias_address;
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+/* Modify sequence number if necessary */
+        if (GetAckModified(link) == 1)
+        {
+            int delta;
+
+            delta = GetDeltaSeqOut(pip, link);
+            if (delta != 0)
+            {
+                sptr = (u_short *) &tc->th_seq;
+                accumulate += *sptr++;
+                accumulate += *sptr;
+                tc->th_seq = htonl(ntohl(tc->th_seq) + delta);
+                sptr = (u_short *) &tc->th_seq;
+                accumulate -= *sptr++;
+                accumulate -= *sptr;
+            }
+        }
+
+        ADJUST_CHECKSUM(accumulate, tc->th_sum)
+
+/* Change source address */
+        sptr = (u_short *) &(pip->ip_src);
+        accumulate  = *sptr++;
+        accumulate += *sptr;
+        pip->ip_src = alias_address;
+        sptr = (u_short *) &(pip->ip_src);
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+        ADJUST_CHECKSUM(accumulate, pip->ip_sum)
+
+        return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_IGNORED);
+}
+
+
+
+
+/* Fragment Handling
+
+    FragmentIn()
+    FragmentOut()
+
+The packet aliasing module has a limited ability for handling IP
+fragments.  If the ICMP, TCP or UDP header is in the first fragment
+received, then the id number of the IP packet is saved, and other
+fragments are identified according to their ID number and IP address
+they were sent from.  Pointers to unresolved fragments can also be
+saved and recalled when a header fragment is seen.
+*/
+
+/* Local prototypes */
+static int FragmentIn(struct ip *);
+static int FragmentOut(struct ip *);
+
+
+static int
+FragmentIn(struct ip *pip)
+{
+    struct alias_link *link;
+
+    link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id);
+    if (link != NULL)
+    {
+        struct in_addr original_address;
+
+        GetFragmentAddr(link, &original_address);
+        DifferentialChecksum(&pip->ip_sum,
+                             (u_short *) &original_address,
+                             (u_short *) &pip->ip_dst,
+                             2);
+        pip->ip_dst = original_address; 
+   
+        return(PKT_ALIAS_OK);
+    }
+    return(PKT_ALIAS_UNRESOLVED_FRAGMENT);
+}
+
+
+static int
+FragmentOut(struct ip *pip)
+{
+    struct in_addr alias_address;
+
+    alias_address = FindAliasAddress(pip->ip_src);
+    DifferentialChecksum(&pip->ip_sum,
+                         (u_short *) &alias_address,
+                         (u_short *) &pip->ip_src,
+                          2);
+    pip->ip_src = alias_address;
+
+    return(PKT_ALIAS_OK);
+}
+
+
+
+
+
+
+/* Outside World Access
+
+        PacketAliasSaveFragment()
+        PacketAliasGetFragment()
+        PacketAliasFragmentIn()
+        PacketAliasIn()
+        PacketAliasOut()
+
+(prototypes in alias.h)
+*/
+
+
+int
+PacketAliasSaveFragment(char *ptr)
+{
+    int iresult;
+    struct alias_link *link;
+    struct ip *pip;
+
+    pip = (struct ip *) ptr;
+    link = AddFragmentPtrLink(pip->ip_src, pip->ip_id);
+    iresult = PKT_ALIAS_ERROR;
+    if (link != NULL)
+    {
+        SetFragmentPtr(link, ptr);
+        iresult = PKT_ALIAS_OK;
+    }
+    return(iresult);
+}
+
+
+char *
+PacketAliasGetFragment(char *ptr)
+{
+    struct alias_link *link;
+    char *fptr;
+    struct ip *pip;
+
+    pip = (struct ip *) ptr;
+    link = FindFragmentPtr(pip->ip_src, pip->ip_id);
+    if (link != NULL)
+    {
+        GetFragmentPtr(link, &fptr);
+        SetFragmentPtr(link, NULL);
+        SetExpire(link, 0); /* Deletes link */
+
+        return(fptr);
+    }
+    else
+    {
+        return(NULL);
+    }
+}
+
+
+void
+PacketAliasFragmentIn(char *ptr,          /* Points to correctly de-aliased
+                                             header fragment */
+                      char *ptr_fragment  /* Points to fragment which must
+                                             be de-aliased   */
+                     )
+{
+    struct ip *pip;
+    struct ip *fpip;
+
+    pip = (struct ip *) ptr;
+    fpip = (struct ip *) ptr_fragment;
+
+    DifferentialChecksum(&fpip->ip_sum,
+                         (u_short *) &pip->ip_dst,
+                         (u_short *) &fpip->ip_dst,
+                         2);
+    fpip->ip_dst = pip->ip_dst;
+}
+
+
+int
+PacketAliasIn(char *ptr, int maxpacketsize)
+{
+    struct in_addr alias_addr;
+    struct ip *pip;
+    int iresult;
+
+    if (packetAliasMode & PKT_ALIAS_REVERSE)
+        return PacketAliasOut(ptr, maxpacketsize);
+
+    HouseKeeping();
+    ClearCheckNewLink();
+    pip = (struct ip *) ptr;
+    alias_addr = pip->ip_dst;
+        
+    /* Defense against mangled packets */
+    if (ntohs(pip->ip_len) > maxpacketsize
+     || (pip->ip_hl<<2) > maxpacketsize)
+        return PKT_ALIAS_IGNORED;
+        
+    iresult = PKT_ALIAS_IGNORED;
+    if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 )
+    {
+        switch (pip->ip_p)
+        {
+            case IPPROTO_ICMP:
+                iresult = IcmpAliasIn(pip);
+                break;
+            case IPPROTO_UDP:
+                iresult = UdpAliasIn(pip);
+                break;
+            case IPPROTO_TCP:
+                iresult = TcpAliasIn(pip);
+                break;
+            case IPPROTO_GRE:
+               iresult = PptpAliasIn(pip);
+                break;
+        }
+
+        if (ntohs(pip->ip_off) & IP_MF)
+        {
+            struct alias_link *link;
+
+            link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id);
+            if (link != NULL)
+            {
+                iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT;
+                SetFragmentAddr(link, pip->ip_dst);
+            }
+            else
+            {
+                iresult = PKT_ALIAS_ERROR;
+            }
+        }
+    }
+    else
+    {
+        iresult = FragmentIn(pip);
+    }
+
+    return(iresult);
+}
+
+
+
+/* Unregistered address ranges */
+
+/* 10.0.0.0   ->   10.255.255.255 */
+#define UNREG_ADDR_A_LOWER 0x0a000000
+#define UNREG_ADDR_A_UPPER 0x0affffff
+
+/* 172.16.0.0  ->  172.31.255.255 */
+#define UNREG_ADDR_B_LOWER 0xac100000
+#define UNREG_ADDR_B_UPPER 0xac1fffff
+
+/* 192.168.0.0 -> 192.168.255.255 */
+#define UNREG_ADDR_C_LOWER 0xc0a80000
+#define UNREG_ADDR_C_UPPER 0xc0a8ffff
+
+int
+PacketAliasOut(char *ptr,           /* valid IP packet */
+               int  maxpacketsize   /* How much the packet data may grow
+                                       (FTP and IRC inline changes) */
+              )
+{
+    int iresult;
+    struct in_addr addr_save;
+    struct ip *pip;
+
+    if (packetAliasMode & PKT_ALIAS_REVERSE)
+        return PacketAliasIn(ptr, maxpacketsize);
+
+    HouseKeeping();
+    ClearCheckNewLink();
+    pip = (struct ip *) ptr;
+
+    /* Defense against mangled packets */
+    if (ntohs(pip->ip_len) > maxpacketsize
+     || (pip->ip_hl<<2) > maxpacketsize)
+        return PKT_ALIAS_IGNORED;
+
+    addr_save = GetDefaultAliasAddress();
+    if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY)
+    {
+        unsigned int addr;
+        int iclass;
+
+        iclass = 0;
+        addr = ntohl(pip->ip_src.s_addr);
+        if      (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER)
+            iclass = 3;
+        else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER)
+            iclass = 2;
+        else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER)
+            iclass = 1;
+
+        if (iclass == 0)
+        {
+            SetDefaultAliasAddress(pip->ip_src);
+        }
+    }
+
+    iresult = PKT_ALIAS_IGNORED;
+    if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0)
+    {
+        switch (pip->ip_p)
+        {
+            case IPPROTO_ICMP:
+                iresult = IcmpAliasOut(pip);
+                break;
+            case IPPROTO_UDP:
+                iresult = UdpAliasOut(pip);
+                break;
+            case IPPROTO_TCP:
+                iresult = TcpAliasOut(pip, maxpacketsize);
+                break;
+            case IPPROTO_GRE:
+               iresult = PptpAliasOut(pip);
+                break;
+        }
+    }
+    else
+    {
+        iresult = FragmentOut(pip);
+    }
+
+    SetDefaultAliasAddress(addr_save);
+    return(iresult);
+}
diff --git a/alias/alias.h b/alias/alias.h
new file mode 100644 (file)
index 0000000..4e0391f
--- /dev/null
@@ -0,0 +1,166 @@
+/*lint -save -library Flexelint comment for external headers */
+
+/*
+    Alias.h defines the outside world interfaces for the packet
+    aliasing software.
+
+    This software is placed into the public domain with no restrictions
+    on its distribution.
+
+    $Id: alias.h,v 1.1.1.1 2000/01/11 01:48:42 wsanchez Exp $
+*/
+
+
+#ifndef _ALIAS_H_
+#define _ALIAS_H_
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Alias link representative (incomplete struct) */
+struct alias_link;
+
+/* External interfaces (API) to packet aliasing engine */
+
+/* Initialization and Control */
+    extern void
+    PacketAliasInit(void);
+
+    extern void
+    PacketAliasUninit(void);
+
+    extern void
+    PacketAliasSetAddress(struct in_addr);
+
+    extern unsigned int
+    PacketAliasSetMode(unsigned int, unsigned int);
+
+#ifndef NO_FW_PUNCH
+    extern void
+    PacketAliasSetFWBase(unsigned int, unsigned int);
+#endif
+
+/* Packet Handling */
+    extern int
+    PacketAliasIn(char *, int maxpacketsize);
+
+    extern int
+    PacketAliasOut(char *, int maxpacketsize);
+
+/* Port and Address Redirection */
+    extern struct alias_link *
+    PacketAliasRedirectPort(struct in_addr, u_short, 
+                            struct in_addr, u_short,
+                            struct in_addr, u_short,
+                            u_char);
+
+    extern int
+    PacketAliasPptp(struct in_addr);
+
+
+    extern struct alias_link *
+    PacketAliasRedirectAddr(struct in_addr,
+                            struct in_addr);
+
+    extern void
+    PacketAliasRedirectDelete(struct alias_link *);
+
+/* Fragment Handling */
+    extern int
+    PacketAliasSaveFragment(char *);
+
+    extern char *
+    PacketAliasGetFragment(char *);
+
+    extern void 
+    PacketAliasFragmentIn(char *, char *);
+
+/* Miscellaneous Functions */
+    extern void
+    PacketAliasSetTarget(struct in_addr addr);
+
+    extern int
+    PacketAliasCheckNewLink(void);
+
+    extern u_short
+    PacketAliasInternetChecksum(u_short *, int);
+
+/* Transparent Proxying */
+    extern int
+    PacketAliasProxyRule(const char *);
+
+
+/********************** Mode flags ********************/
+/* Set these flags using SetPacketAliasMode() */
+
+/* If PKT_ALIAS_LOG is set, a message will be printed to
+       /var/log/alias.log every time a link is created or deleted.  This
+       is useful for debugging */
+#define PKT_ALIAS_LOG 0x01
+
+/* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g.
+       to ftp, telnet or web servers will be prevented by the aliasing
+       mechanism.  */
+#define PKT_ALIAS_DENY_INCOMING 0x02
+
+/* If PKT_ALIAS_SAME_PORTS is set, packets will be attempted sent from
+       the same port as they originated on.  This allows eg rsh to work
+       *99% of the time*, but _not_ 100%.  (It will be slightly flakey
+       instead of not working at all.)  This mode bit is set by
+        PacketAliasInit(), so it is a default mode of operation. */
+#define PKT_ALIAS_SAME_PORTS 0x04
+
+/* If PKT_ALIAS_USE_SOCKETS is set, then when partially specified
+       links (e.g. destination port and/or address is zero), the packet
+       aliasing engine will attempt to allocate a socket for the aliasing
+       port it chooses.  This will avoid interference with the host
+       machine.  Fully specified links do not require this.  This bit
+        is set after a call to PacketAliasInit(), so it is a default
+        mode of operation.*/
+#define PKT_ALIAS_USE_SOCKETS 0x08
+
+/* If PKT_ALIAS_UNREGISTERED_ONLY is set, then only packets with with
+       unregistered source addresses will be aliased (along with those
+       of the ppp host maching itself.  Private addresses are those
+        in the following ranges:
+               10.0.0.0     ->   10.255.255.255
+               172.16.0.0   ->   172.31.255.255
+               192.168.0.0  ->   192.168.255.255  */
+#define PKT_ALIAS_UNREGISTERED_ONLY 0x10
+
+/* If PKT_ALIAS_RESET_ON_ADDR_CHANGE is set, then the table of dynamic
+       aliasing links will be reset whenever PacketAliasSetAddress()
+        changes the default aliasing address.  If the default aliasing
+        address is left unchanged by this functions call, then the
+        table of dynamic aliasing links will be left intact.  This
+        bit is set after a call to PacketAliasInit(). */
+#define PKT_ALIAS_RESET_ON_ADDR_CHANGE 0x20
+
+#ifndef NO_FW_PUNCH
+/* If PKT_ALIAS_PUNCH_FW is set, active FTP and IRC DCC connections
+   will create a 'hole' in the firewall to allow the transfers to
+   work.  Where (IPFW "line-numbers") the hole is created is
+   controlled by PacketAliasSetFWBase(base, size). The hole will be
+   attached to that particular alias_link, so when the link goes away
+   so do the hole.  */
+#define PKT_ALIAS_PUNCH_FW 0x40
+#endif
+
+/* If PKT_ALIAS_PROXY_ONLY is set, then NAT will be disabled and only
+      transparent proxying performed */
+#define PKT_ALIAS_PROXY_ONLY 0x40
+
+/* If PKT_ALIAS_REVERSE is set, the actions of PacketAliasIn()
+      and PacketAliasOut() are reversed */
+#define PKT_ALIAS_REVERSE 0x80
+
+/* Return Codes */
+#define PKT_ALIAS_ERROR -1
+#define PKT_ALIAS_OK 1
+#define PKT_ALIAS_IGNORED 2
+#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3
+#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4
+
+#endif
+/*lint -restore */
diff --git a/alias/alias_cuseeme.c b/alias/alias_cuseeme.c
new file mode 100644 (file)
index 0000000..a78f041
--- /dev/null
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ *                    with the aid of code written by
+ *                    Junichi SATOH <junichi@astec.co.jp> 1996, 1997.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $Id: alias_cuseeme.c,v 1.1.1.1 2000/01/11 01:48:42 wsanchez Exp $
+ */
+
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
+#include "alias_local.h"
+
+/* CU-SeeMe Data Header */
+struct cu_header {
+    u_int16_t dest_family;
+    u_int16_t dest_port;
+    u_int32_t  dest_addr;
+    int16_t family;
+    u_int16_t port;
+    u_int32_t addr;
+    u_int32_t seq;
+    u_int16_t msg;
+    u_int16_t data_type;
+    u_int16_t packet_len;
+};
+
+/* Open Continue Header */
+struct oc_header {
+    u_int16_t client_count;    /* Number of client info structs */
+    u_int32_t seq_no;
+    char user_name[20];
+    char reserved[4];        /* flags, version stuff, etc */
+};
+
+/* client info structures */
+struct client_info {
+    u_int32_t address;          /* Client address */
+    char reserved[8];        /* Flags, pruning bitfield, packet counts etc */
+};
+
+void
+AliasHandleCUSeeMeOut(struct ip *pip, struct alias_link *link)
+{
+  struct udphdr *ud;
+
+  ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2));
+  if(ud->uh_ulen >= sizeof(struct cu_header)) {
+    struct cu_header *cu;
+    struct alias_link *cu_link;
+
+    cu = (struct cu_header *)(ud + 1);
+    if (cu->addr)
+      cu->addr = (u_int32_t)GetAliasAddress(link).s_addr;
+
+    cu_link = FindUdpTcpOut(pip->ip_src, GetDestAddress(link),
+                            ud->uh_dport, 0, IPPROTO_UDP);
+                         
+#ifndef NO_FW_PUNCH
+    if (cu_link)
+        PunchFWHole(cu_link);
+#endif
+  }
+}
+
+void
+AliasHandleCUSeeMeIn(struct ip *pip, struct in_addr original_addr)
+{
+  struct in_addr alias_addr;
+  struct udphdr *ud;
+  struct cu_header *cu;
+  struct oc_header *oc;
+  struct client_info *ci;
+  char *end;
+  int i;
+
+  alias_addr.s_addr = pip->ip_dst.s_addr;
+  ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2));
+  cu = (struct cu_header *)(ud + 1);
+  oc = (struct oc_header *)(cu + 1);
+  ci = (struct client_info *)(oc + 1);
+  end = (char *)cu + ud->uh_ulen;
+
+  if ((char *)oc <= end) {
+    if(cu->dest_addr)
+      cu->dest_addr = (u_int32_t)original_addr.s_addr;
+    if(ntohs(cu->data_type) == 101)
+      /* Find and change our address */
+      for(i = 0; (char *)(ci + 1) <= end && i < oc->client_count; i++, ci++)
+        if(ci->address == (u_int32_t)alias_addr.s_addr) {
+          ci->address = (u_int32_t)original_addr.s_addr;
+          break;
+        }
+  }
+}
diff --git a/alias/alias_db.c b/alias/alias_db.c
new file mode 100644 (file)
index 0000000..d01188e
--- /dev/null
@@ -0,0 +1,2330 @@
+/*  -*- mode: c; tab-width: 8; c-basic-indent: 4; -*-
+    Alias_db.c encapsulates all data structures used for storing
+    packet aliasing data.  Other parts of the aliasing software
+    access data through functions provided in this file.
+
+    Data storage is based on the notion of a "link", which is
+    established for ICMP echo/reply packets, UDP datagrams and
+    TCP stream connections.  A link stores the original source
+    and destination addresses.  For UDP and TCP, it also stores
+    source and destination port numbers, as well as an alias
+    port number.  Links are also used to store information about
+    fragments.
+
+    There is a facility for sweeping through and deleting old
+    links as new packets are sent through.  A simple timeout is
+    used for ICMP and UDP links.  TCP links are left alone unless
+    there is an incomplete connection, in which case the link
+    can be deleted after a certain amount of time.
+
+
+    This software is placed into the public domain with no restrictions
+    on its distribution.
+
+    Initial version: August, 1996  (cjm)
+
+    Version 1.4: September 16, 1996 (cjm)
+        Facility for handling incoming links added.
+
+    Version 1.6: September 18, 1996 (cjm)
+        ICMP data handling simplified.
+
+    Version 1.7: January 9, 1997 (cjm)
+        Fragment handling simplified.
+        Saves pointers for unresolved fragments.
+        Permits links for unspecied remote ports
+          or unspecified remote addresses.
+        Fixed bug which did not properly zero port
+          table entries after a link was deleted.
+        Cleaned up some obsolete comments.
+
+    Version 1.8: January 14, 1997 (cjm)
+        Fixed data type error in StartPoint().
+        (This error did not exist prior to v1.7
+        and was discovered and fixed by Ari Suutari)
+
+    Version 1.9: February 1, 1997
+        Optionally, connections initiated from packet aliasing host
+        machine will will not have their port number aliased unless it
+        conflicts with an aliasing port already being used. (cjm)
+
+        All options earlier being #ifdef'ed now are available through
+        a new interface, SetPacketAliasMode().  This allow run time
+        control (which is now available in PPP+pktAlias through the
+        'alias' keyword). (ee)
+
+        Added ability to create an alias port without
+        either destination address or port specified.
+        port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee)
+
+        Removed K&R style function headers
+        and general cleanup. (ee)
+
+        Added packetAliasMode to replace compiler #defines's (ee)
+
+        Allocates sockets for partially specified
+        ports if ALIAS_USE_SOCKETS defined. (cjm)
+
+    Version 2.0: March, 1997
+        SetAliasAddress() will now clean up alias links
+        if the aliasing address is changed. (cjm)
+
+        PacketAliasPermanentLink() function added to support permanent
+        links.  (J. Fortes suggested the need for this.)
+        Examples:
+
+        (192.168.0.1, port 23)  <-> alias port 6002, unknown dest addr/port
+
+        (192.168.0.2, port 21)  <-> alias port 3604, known dest addr
+                                                     unknown dest port
+
+        These permament links allow for incoming connections to
+        machines on the local network.  They can be given with a
+        user-chosen amount of specificity, with increasing specificity
+        meaning more security. (cjm)
+
+        Quite a bit of rework to the basic engine.  The portTable[]
+        array, which kept track of which ports were in use was replaced
+        by a table/linked list structure. (cjm)
+
+        SetExpire() function added. (cjm)
+
+        DeleteLink() no longer frees memory association with a pointer
+        to a fragment (this bug was first recognized by E. Eklund in
+        v1.9).
+
+    Version 2.1: May, 1997 (cjm)
+        Packet aliasing engine reworked so that it can handle
+        multiple external addresses rather than just a single
+        host address.
+
+        PacketAliasRedirectPort() and PacketAliasRedirectAddr()
+        added to the API.  The first function is a more generalized
+        version of PacketAliasPermanentLink().  The second function
+        implements static network address translation.
+
+    See HISTORY file for additional revisions.
+*/
+
+
+/* System include files */
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+/* BSD network include files */
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include "alias.h"
+#include "alias_local.h"
+
+
+
+/*
+   Constants (note: constants are also defined
+              near relevant functions or structs)
+*/
+
+/* Sizes of input and output link tables */
+#define LINK_TABLE_OUT_SIZE         101
+#define LINK_TABLE_IN_SIZE         4001
+
+/* Parameters used for cleanup of expired links */
+#define ALIAS_CLEANUP_INTERVAL_SECS  60
+#define ALIAS_CLEANUP_MAX_SPOKES     30
+
+/* Timouts (in seconds) for different link types) */
+#define ICMP_EXPIRE_TIME             60
+#define UDP_EXPIRE_TIME              60
+#define FRAGMENT_ID_EXPIRE_TIME      10
+#define FRAGMENT_PTR_EXPIRE_TIME     30
+
+/* TCP link expire time for different cases */
+/* When the link has been used and closed - minimal grace time to
+   allow ACKs and potential re-connect in FTP (XXX - is this allowed?)  */
+#ifndef TCP_EXPIRE_DEAD
+#   define TCP_EXPIRE_DEAD           10
+#endif
+
+/* When the link has been used and closed on one side - the other side
+   is allowed to still send data */
+#ifndef TCP_EXPIRE_SINGLEDEAD
+#   define TCP_EXPIRE_SINGLEDEAD     90
+#endif
+
+/* When the link isn't yet up */
+#ifndef TCP_EXPIRE_INITIAL
+#   define TCP_EXPIRE_INITIAL       300
+#endif
+
+/* When the link is up */
+#ifndef TCP_EXPIRE_CONNECTED
+#   define TCP_EXPIRE_CONNECTED   86400
+#endif
+
+
+/* Dummy port number codes used for FindLinkIn/Out() and AddLink().
+   These constants can be anything except zero, which indicates an
+   unknown port number. */
+
+#define NO_DEST_PORT     1
+#define NO_SRC_PORT      1
+
+
+
+/* Data Structures
+
+    The fundamental data structure used in this program is
+    "struct alias_link".  Whenever a TCP connection is made,
+    a UDP datagram is sent out, or an ICMP echo request is made,
+    a link record is made (if it has not already been created).
+    The link record is identified by the source address/port
+    and the destination address/port. In the case of an ICMP
+    echo request, the source port is treated as being equivalent
+    with the 16-bit id number of the ICMP packet.
+
+    The link record also can store some auxiliary data.  For
+    TCP connections that have had sequence and acknowledgment
+    modifications, data space is available to track these changes.
+    A state field is used to keep track in changes to the tcp
+    connection state.  Id numbers of fragments can also be
+    stored in the auxiliary space.  Pointers to unresolved
+    framgents can also be stored.
+
+    The link records support two independent chainings.  Lookup
+    tables for input and out tables hold the initial pointers
+    the link chains.  On input, the lookup table indexes on alias
+    port and link type.  On output, the lookup table indexes on
+    source addreess, destination address, source port, destination
+    port and link type.
+*/
+
+struct ack_data_record     /* used to save changes to ack/seq numbers */
+{
+    u_long ack_old;
+    u_long ack_new;
+    int delta;
+    int active;
+};
+
+struct tcp_state           /* Information about tcp connection        */
+{
+    int in;                /* State for outside -> inside             */
+    int out;               /* State for inside  -> outside            */
+    int index;             /* Index to ack data array                 */
+    int ack_modified;      /* Indicates whether ack and seq numbers   */
+                           /* been modified                           */
+};
+
+#define N_LINK_TCP_DATA   3 /* Number of distinct ack number changes
+                               saved for a modified TCP stream */
+struct tcp_dat
+{
+    struct tcp_state state;
+    struct ack_data_record ack[N_LINK_TCP_DATA];
+    int fwhole;             /* Which firewall record is used for this hole? */
+};
+
+struct alias_link                /* Main data structure */
+{
+    struct in_addr src_addr;     /* Address and port information        */
+    struct in_addr dst_addr;
+    struct in_addr alias_addr;
+    struct in_addr proxy_addr;
+    u_short src_port;
+    u_short dst_port;
+    u_short alias_port;
+    u_short proxy_port;
+
+    int link_type;               /* Type of link: tcp, udp, icmp, frag  */
+
+/* values for link_type */
+#define LINK_ICMP                     1
+#define LINK_UDP                      2
+#define LINK_TCP                      3
+#define LINK_FRAGMENT_ID              4
+#define LINK_FRAGMENT_PTR             5
+#define LINK_ADDR                     6
+
+    int flags;                   /* indicates special characteristics   */
+
+/* flag bits */
+#define LINK_UNKNOWN_DEST_PORT     0x01
+#define LINK_UNKNOWN_DEST_ADDR     0x02
+#define LINK_PERMANENT             0x04
+#define LINK_PARTIALLY_SPECIFIED   0x03 /* logical-or of first two bits */
+#define LINK_UNFIREWALLED          0x08
+
+    int timestamp;               /* Time link was last accessed         */
+    int expire_time;             /* Expire time for link                */
+
+    int sockfd;                  /* socket descriptor                   */
+
+    u_int start_point_out;       /* Index number in output lookup table */
+    u_int start_point_in;
+    struct alias_link *next_out; /* Linked list pointers for input and  */
+    struct alias_link *last_out; /* output tables                       */
+    struct alias_link *next_in;  /*  .                                  */
+    struct alias_link *last_in;  /*  .                                  */
+
+    union                        /* Auxiliary data                      */
+    {
+        char *frag_ptr;
+        struct in_addr frag_addr;
+        struct tcp_dat *tcp;
+    } data;
+};
+
+
+
+
+
+/* Global Variables 
+
+    The global variables listed here are only accessed from
+    within alias_db.c and so are prefixed with the static 
+    designation.
+*/
+
+int packetAliasMode;                 /* Mode flags                      */ 
+                                     /*        - documented in alias.h  */
+
+static struct in_addr aliasAddress;  /* Address written onto source     */
+                                     /*   field of IP packet.           */
+
+static struct in_addr targetAddress; /* IP address incoming packets     */
+                                     /*   are sent to if no aliasing    */
+                                     /*   link already exists           */
+
+static struct in_addr nullAddress;   /* Used as a dummy parameter for   */
+                                     /*   some function calls           */
+static struct alias_link *
+linkTableOut[LINK_TABLE_OUT_SIZE];   /* Lookup table of pointers to     */
+                                     /*   chains of link records. Each  */
+static struct alias_link *           /*   link record is doubly indexed */
+linkTableIn[LINK_TABLE_IN_SIZE];     /*   into input and output lookup  */
+                                     /*   tables.                       */
+
+static int icmpLinkCount;            /* Link statistics                 */
+static int udpLinkCount;
+static int tcpLinkCount;
+static int fragmentIdLinkCount;
+static int fragmentPtrLinkCount;
+static int sockCount;
+
+static int cleanupIndex;             /* Index to chain of link table    */
+                                     /* being inspected for old links   */
+
+static int timeStamp;                /* System time in seconds for      */
+                                     /* current packet                  */
+
+static int lastCleanupTime;          /* Last time IncrementalCleanup()  */
+                                     /* was called                      */
+
+static int houseKeepingResidual;     /* used by HouseKeeping()          */
+
+static int deleteAllLinks;           /* If equal to zero, DeleteLink()  */
+                                     /* will not remove permanent links */
+
+static FILE *monitorFile;            /* File descriptor for link        */
+                                     /* statistics monitoring file      */
+
+static int newDefaultLink;           /* Indicates if a new aliasing     */
+                                     /* link has been created after a   */
+                                     /* call to PacketAliasIn/Out().    */
+             
+#ifndef NO_FW_PUNCH
+static int fireWallFD = -1;          /* File descriptor to be able to   */
+                                     /* control firewall.  Opened by    */
+                                     /* PacketAliasSetMode on first     */
+                                     /* setting the PKT_ALIAS_PUNCH_FW  */
+                                     /* flag.                           */
+#endif
+
+static int pptpAliasFlag;           /* Indicates if PPTP aliasing is   */
+                                     /* on or off                       */
+static struct in_addr pptpAliasAddr; /* Address of source of PPTP      */
+                                     /* packets.                       */
+
+
+
+
+
+
+
+/* Internal utility routines (used only in alias_db.c)
+
+Lookup table starting points:
+    StartPointIn()           -- link table initial search point for
+                                outgoing packets
+    StartPointOut()          -- port table initial search point for
+                                incoming packets
+    
+Miscellaneous:
+    SeqDiff()                -- difference between two TCP sequences
+    ShowAliasStats()         -- send alias statistics to a monitor file
+*/
+
+
+/* Local prototypes */
+static u_int StartPointIn(struct in_addr, u_short, int);
+
+static u_int StartPointOut(struct in_addr, struct in_addr,
+                           u_short, u_short, int);
+
+static int SeqDiff(u_long, u_long);
+
+static void ShowAliasStats(void);
+
+#ifndef NO_FW_PUNCH
+/* Firewall control */
+static void InitPunchFW(void);
+static void UninitPunchFW(void);
+static void ClearFWHole(struct alias_link *link);
+#endif
+
+/* Log file control */
+static void InitPacketAliasLog(void);
+static void UninitPacketAliasLog(void);
+
+static u_int
+StartPointIn(struct in_addr alias_addr,
+             u_short alias_port,
+             int link_type)
+{
+    u_int n;
+
+    n  = alias_addr.s_addr;
+    n += alias_port;
+    n += link_type;
+    return(n % LINK_TABLE_IN_SIZE);
+}
+
+
+static u_int
+StartPointOut(struct in_addr src_addr, struct in_addr dst_addr,
+              u_short src_port, u_short dst_port, int link_type)
+{
+    u_int n;
+
+    n  = src_addr.s_addr;
+    n += dst_addr.s_addr;
+    n += src_port; 
+    n += dst_port;
+    n += link_type;
+
+    return(n % LINK_TABLE_OUT_SIZE);
+}
+
+
+static int
+SeqDiff(u_long x, u_long y)
+{
+/* Return the difference between two TCP sequence numbers */
+
+/*
+    This function is encapsulated in case there are any unusual
+    arithmetic conditions that need to be considered.
+*/
+
+    return (ntohl(y) - ntohl(x));
+}
+
+
+static void
+ShowAliasStats(void)
+{
+/* Used for debugging */
+
+   if (monitorFile)
+   {
+      fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, frag_id=%d frag_ptr=%d",
+              icmpLinkCount,
+              udpLinkCount,
+              tcpLinkCount,
+              fragmentIdLinkCount,
+              fragmentPtrLinkCount);
+
+      fprintf(monitorFile, " / tot=%d  (sock=%d)\n",
+              icmpLinkCount + udpLinkCount
+                            + tcpLinkCount
+                            + fragmentIdLinkCount
+                            + fragmentPtrLinkCount,
+              sockCount);
+
+      fflush(monitorFile);
+   }
+}
+
+
+
+
+
+/* Internal routines for finding, deleting and adding links
+
+Port Allocation:
+    GetNewPort()             -- find and reserve new alias port number
+    GetSocket()              -- try to allocate a socket for a given port
+
+Link creation and deletion:
+    CleanupAliasData()      - remove all link chains from lookup table
+    IncrementalCleanup()    - look for stale links in a single chain
+    DeleteLink()            - remove link
+    AddLink()               - add link 
+    ReLink()                - change link 
+
+Link search:
+    FindLinkOut()           - find link for outgoing packets
+    FindLinkIn()            - find link for incoming packets
+*/
+
+/* Local prototypes */
+static int GetNewPort(struct alias_link *, int);
+
+static u_short GetSocket(u_short, int *, int);
+
+static void CleanupAliasData(void);
+
+static void IncrementalCleanup(void);
+
+static void DeleteLink(struct alias_link *);
+
+static struct alias_link *
+AddLink(struct in_addr, struct in_addr, struct in_addr,
+        u_short, u_short, int, int);
+
+static struct alias_link *
+ReLink(struct alias_link *,
+       struct in_addr, struct in_addr, struct in_addr,
+        u_short, u_short, int, int);
+
+static struct alias_link *
+FindLinkOut(struct in_addr, struct in_addr, u_short, u_short, int);
+
+static struct alias_link *
+FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int);
+
+
+#define ALIAS_PORT_BASE            0x08000
+#define ALIAS_PORT_MASK            0x07fff
+#define GET_NEW_PORT_MAX_ATTEMPTS       20
+
+#define GET_ALIAS_PORT                  -1
+#define GET_ALIAS_ID        GET_ALIAS_PORT
+
+/* GetNewPort() allocates port numbers.  Note that if a port number
+   is already in use, that does not mean that it cannot be used by
+   another link concurrently.  This is because GetNewPort() looks for
+   unused triplets: (dest addr, dest port, alias port). */
+
+static int
+GetNewPort(struct alias_link *link, int alias_port_param)
+{
+    int i;
+    int max_trials;
+    u_short port_sys;
+    u_short port_net;
+
+/*
+   Description of alias_port_param for GetNewPort().  When
+   this parameter is zero or positive, it precisely specifies
+   the port number.  GetNewPort() will return this number
+   without check that it is in use.
+
+   Whis this parameter is -1, it indicates to get a randomly
+   selected port number.
+*/
+    if (alias_port_param == GET_ALIAS_PORT)
+    {
+        /*
+         * The aliasing port is automatically selected
+         * by one of two methods below:
+         */
+        max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
+
+        if (packetAliasMode & PKT_ALIAS_SAME_PORTS)
+        {
+            /*
+             * When the ALIAS_SAME_PORTS option is
+             * chosen, the first try will be the
+             * actual source port. If this is already
+             * in use, the remainder of the trials
+             * will be random.
+             */
+            port_net = link->src_port;
+            port_sys = ntohs(port_net);
+        }
+        else
+        {
+            /* First trial and all subsequent are random. */
+            port_sys = random() & ALIAS_PORT_MASK;
+            port_sys += ALIAS_PORT_BASE;
+            port_net = htons(port_sys);
+        }
+    }
+    else if (alias_port_param >= 0 && alias_port_param < 0x10000)
+    {
+        link->alias_port = (u_short) alias_port_param;
+        return(0);
+    }
+    else
+    {
+#ifdef DEBUG
+        fprintf(stderr, "PacketAlias/GetNewPort(): ");
+        fprintf(stderr, "input parameter error\n");
+#endif
+        return(-1);
+    }
+
+
+/* Port number search */
+    for (i=0; i<max_trials; i++)
+    {
+        int go_ahead;
+        struct alias_link *search_result;
+
+        search_result = FindLinkIn(link->dst_addr, link->alias_addr,
+                                   link->dst_port, port_net,
+                                   link->link_type, 0);
+
+        if (search_result == NULL)
+            go_ahead = 1;
+        else if (!(link->flags          & LINK_PARTIALLY_SPECIFIED)
+               && (search_result->flags & LINK_PARTIALLY_SPECIFIED))
+            go_ahead = 1;
+        else
+            go_ahead = 0;
+
+        if (go_ahead)
+        {
+            if ((packetAliasMode && PKT_ALIAS_USE_SOCKETS)
+             && (link->flags & LINK_PARTIALLY_SPECIFIED))
+            {
+                if (GetSocket(port_net, &link->sockfd, link->link_type))
+                {
+                    link->alias_port = port_net;
+                    return(0);
+                }
+            }
+            else
+            {
+                link->alias_port = port_net;
+                return(0);
+            }
+        }
+
+        port_sys = random() & ALIAS_PORT_MASK;
+        port_sys += ALIAS_PORT_BASE;
+        port_net = htons(port_sys);
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, "PacketAlias/GetnewPort(): ");
+    fprintf(stderr, "could not find free port\n");
+#endif
+
+    return(-1);
+}
+
+
+static u_short 
+GetSocket(u_short port_net, int *sockfd, int link_type)
+{
+    int err;
+    int sock;
+    struct sockaddr_in sock_addr;
+
+    if (link_type == LINK_TCP)
+        sock = socket(AF_INET, SOCK_STREAM, 0);
+    else if (link_type == LINK_UDP)
+        sock = socket(AF_INET, SOCK_DGRAM, 0);
+    else
+    {
+#ifdef DEBUG
+        fprintf(stderr, "PacketAlias/GetSocket(): ");
+        fprintf(stderr, "incorrect link type\n");
+#endif
+        return(0);
+    }
+
+    if (sock < 0)
+    {
+#ifdef DEBUG
+        fprintf(stderr, "PacketAlias/GetSocket(): ");
+        fprintf(stderr, "socket() error %d\n", *sockfd);
+#endif
+        return(0);
+    }
+
+    sock_addr.sin_family = AF_INET;
+    sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    sock_addr.sin_port = port_net;
+
+    err = bind(sock,
+               (struct sockaddr *) &sock_addr,
+               sizeof(sock_addr));
+    if (err == 0)
+    {
+        sockCount++;
+        *sockfd = sock;
+        return(1);
+    }
+    else
+    {
+        close(sock);
+        return(0);
+    }
+}
+
+
+static void
+CleanupAliasData(void)
+{
+    struct alias_link *link;
+    int i, icount;
+
+    icount = 0;
+    for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
+    {
+        link = linkTableOut[i];
+        while (link != NULL)
+        {
+            struct alias_link *link_next;
+            link_next = link->next_out;
+            icount++;
+            DeleteLink(link);
+            link = link_next;
+        }
+    }
+
+    cleanupIndex =0;
+}
+
+
+static void
+IncrementalCleanup(void)
+{
+    int icount;
+    struct alias_link *link;
+
+    icount = 0;
+    link = linkTableOut[cleanupIndex++];
+    while (link != NULL)
+    {
+        int idelta;
+        struct alias_link *link_next;
+
+        link_next = link->next_out; 
+        idelta = timeStamp - link->timestamp;
+        switch (link->link_type)
+        {
+            case LINK_ICMP:
+            case LINK_UDP:
+            case LINK_FRAGMENT_ID:
+            case LINK_FRAGMENT_PTR:
+                if (idelta > link->expire_time)
+                {
+                    DeleteLink(link);
+                    icount++;
+                }
+                break;
+            case LINK_TCP:
+                if (idelta > link->expire_time)
+                {
+                    struct tcp_dat *tcp_aux;
+
+                    tcp_aux = link->data.tcp; 
+                    if (tcp_aux->state.in  != ALIAS_TCP_STATE_CONNECTED
+                     || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED)
+                    {
+                        DeleteLink(link);
+                        icount++;
+                    }
+                }
+                break;
+        }
+        link = link_next;
+    }
+
+    if (cleanupIndex == LINK_TABLE_OUT_SIZE)
+        cleanupIndex = 0;
+}
+
+void
+DeleteLink(struct alias_link *link)
+{
+    struct alias_link *link_last;
+    struct alias_link *link_next;
+
+/* Don't do anything if the link is marked permanent */
+    if (deleteAllLinks == 0 && link->flags & LINK_PERMANENT)
+        return;
+
+#ifndef NO_FW_PUNCH
+/* Delete associatied firewall hole, if any */
+    ClearFWHole(link);
+#endif
+
+/* Adjust output table pointers */
+    link_last = link->last_out;
+    link_next = link->next_out;
+
+    if (link_last != NULL)
+        link_last->next_out = link_next;
+    else
+        linkTableOut[link->start_point_out] = link_next;
+
+    if (link_next != NULL)
+        link_next->last_out = link_last;
+
+/* Adjust input table pointers */
+    link_last = link->last_in;
+    link_next = link->next_in;
+
+    if (link_last != NULL)
+        link_last->next_in = link_next;
+    else
+        linkTableIn[link->start_point_in] = link_next;
+
+    if (link_next != NULL)
+        link_next->last_in = link_last;
+
+/* Close socket, if one has been allocated */
+    if (link->sockfd != -1)
+    {
+        sockCount--;
+        close(link->sockfd);
+    }
+
+/* Link-type dependent cleanup */
+    switch(link->link_type)
+    {
+        case LINK_ICMP:
+            icmpLinkCount--;
+            break;
+        case LINK_UDP:
+            udpLinkCount--;
+            break;
+        case LINK_TCP:
+            tcpLinkCount--;
+            if (link->data.tcp != NULL)
+                free(link->data.tcp);
+            break;
+        case LINK_FRAGMENT_ID:
+            fragmentIdLinkCount--;
+            break;
+        case LINK_FRAGMENT_PTR:
+            fragmentPtrLinkCount--;
+            if (link->data.frag_ptr != NULL)
+                free(link->data.frag_ptr);
+            break;
+    }
+
+/* Free memory */
+    free(link);
+
+/* Write statistics, if logging enabled */
+    if (packetAliasMode & PKT_ALIAS_LOG)
+    {
+        ShowAliasStats();
+    }
+}
+
+
+static struct alias_link *
+AddLink(struct in_addr  src_addr,
+        struct in_addr  dst_addr,
+        struct in_addr  alias_addr,
+        u_short         src_port,
+        u_short         dst_port,
+        int             alias_port_param,  /* if less than zero, alias   */
+        int             link_type)         /* port will be automatically */
+{                                          /* chosen. If greater than    */
+    u_int start_point;                     /* zero, equal to alias port  */
+    struct alias_link *link;
+    struct alias_link *first_link;
+
+    link = malloc(sizeof(struct alias_link));
+    if (link != NULL)
+    {
+    /* If either the aliasing address or source address are
+       equal to the default device address (equal to the
+       global variable aliasAddress), then set the alias
+       address field of the link record to zero */
+
+        if (src_addr.s_addr == aliasAddress.s_addr)
+            src_addr.s_addr = 0;
+
+        if (alias_addr.s_addr == aliasAddress.s_addr)
+            alias_addr.s_addr = 0;
+
+    /* Basic initialization */
+        link->src_addr          = src_addr;
+        link->dst_addr          = dst_addr;
+        link->alias_addr        = alias_addr;
+        link->proxy_addr.s_addr = 0;
+        link->src_port          = src_port;
+        link->dst_port          = dst_port;
+        link->proxy_port        = 0;
+        link->link_type         = link_type;
+        link->sockfd            = -1;
+        link->flags             = 0;
+        link->timestamp         = timeStamp;
+
+    /* Expiration time */
+        switch (link_type)
+        {
+        case LINK_ICMP:
+            link->expire_time = ICMP_EXPIRE_TIME;
+            break;
+        case LINK_UDP:
+            link->expire_time = UDP_EXPIRE_TIME;
+            break;
+        case LINK_TCP:
+            link->expire_time = TCP_EXPIRE_INITIAL;
+            break;
+        case LINK_FRAGMENT_ID:
+            link->expire_time = FRAGMENT_ID_EXPIRE_TIME;
+            break;
+        case LINK_FRAGMENT_PTR:
+            link->expire_time = FRAGMENT_PTR_EXPIRE_TIME;
+            break;
+        }
+
+    /* Determine alias flags */
+        if (dst_addr.s_addr == 0)
+            link->flags |= LINK_UNKNOWN_DEST_ADDR;
+        if (dst_port == 0)
+            link->flags |= LINK_UNKNOWN_DEST_PORT;
+
+    /* Determine alias port */
+        if (GetNewPort(link, alias_port_param) != 0)
+        {
+            free(link);
+            return(NULL);
+        }
+
+    /* Set up pointers for output lookup table */
+        start_point = StartPointOut(src_addr, dst_addr, 
+                                    src_port, dst_port, link_type);
+        first_link = linkTableOut[start_point];
+
+        link->last_out        = NULL;
+        link->next_out        = first_link;
+        link->start_point_out = start_point;
+
+        if (first_link != NULL)
+            first_link->last_out = link;
+
+        linkTableOut[start_point] = link;
+
+    /* Set up pointers for input lookup table */
+        start_point = StartPointIn(alias_addr, link->alias_port, link_type); 
+        first_link = linkTableIn[start_point];
+
+        link->last_in        = NULL;
+        link->next_in        = first_link;
+        link->start_point_in = start_point;
+
+        if (first_link != NULL)
+            first_link->last_in = link;
+
+        linkTableIn[start_point] = link;
+
+    /* Link-type dependent initialization */
+        switch(link_type)
+        {
+            struct tcp_dat  *aux_tcp;
+
+            case LINK_ICMP:
+                icmpLinkCount++;
+                break;
+            case LINK_UDP:
+                udpLinkCount++;
+                break;
+            case LINK_TCP:
+                aux_tcp = malloc(sizeof(struct tcp_dat));
+                link->data.tcp = aux_tcp;
+                if (aux_tcp != NULL)
+                {
+                    int i;
+
+                    tcpLinkCount++;
+                    aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED;
+                    aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED;
+                    aux_tcp->state.index = 0;
+                    aux_tcp->state.ack_modified = 0;
+                    for (i=0; i<N_LINK_TCP_DATA; i++)
+                        aux_tcp->ack[i].active = 0;
+                    aux_tcp->fwhole = -1;
+                }
+                else
+                {
+#ifdef DEBUG
+                    fprintf(stderr, "PacketAlias/AddLink: ");
+                    fprintf(stderr, " cannot allocate auxiliary TCP data\n");
+#endif
+                }
+                break;
+            case LINK_FRAGMENT_ID:
+                fragmentIdLinkCount++;
+                break;
+            case LINK_FRAGMENT_PTR:
+                fragmentPtrLinkCount++;
+                break;
+        }
+    }
+    else
+    {
+#ifdef DEBUG
+        fprintf(stderr, "PacketAlias/AddLink(): ");
+        fprintf(stderr, "malloc() call failed.\n");
+#endif
+    }
+
+    if (packetAliasMode & PKT_ALIAS_LOG)
+    {
+        ShowAliasStats();
+    }
+
+    return(link);
+}
+
+static struct alias_link *
+ReLink(struct alias_link *old_link,
+       struct in_addr  src_addr,
+       struct in_addr  dst_addr,
+       struct in_addr  alias_addr,
+       u_short         src_port,
+       u_short         dst_port,
+       int             alias_port_param,   /* if less than zero, alias   */
+       int             link_type)          /* port will be automatically */
+{                                          /* chosen. If greater than    */
+    struct alias_link *new_link;           /* zero, equal to alias port  */
+
+    new_link = AddLink(src_addr, dst_addr, alias_addr,
+                       src_port, dst_port, alias_port_param,
+                       link_type);
+#ifndef NO_FW_PUNCH
+    if (new_link != NULL &&
+        old_link->link_type == LINK_TCP &&
+        old_link->data.tcp &&
+        old_link->data.tcp->fwhole > 0) {
+      PunchFWHole(new_link);
+    }
+#endif
+    DeleteLink(old_link);
+    return new_link;
+}
+
+static struct alias_link *
+FindLinkOut(struct in_addr src_addr,
+            struct in_addr dst_addr,
+            u_short src_port,
+            u_short dst_port,
+            int link_type)
+{
+    u_int i;
+    struct alias_link *link;
+
+    if (src_addr.s_addr == aliasAddress.s_addr)
+        src_addr.s_addr = 0;
+
+    i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type);
+    link = linkTableOut[i];
+    while (link != NULL)
+    {
+        if (link->src_addr.s_addr == src_addr.s_addr
+         && link->dst_addr.s_addr == dst_addr.s_addr
+         && link->dst_port        == dst_port
+         && link->src_port        == src_port
+         && link->link_type       == link_type)
+        {
+            link->timestamp = timeStamp;
+            break;
+        }
+        link = link->next_out;
+    }
+
+    return(link);
+}
+
+
+struct alias_link *
+FindLinkIn(struct in_addr  dst_addr,
+           struct in_addr  alias_addr,
+           u_short         dst_port,
+           u_short         alias_port,
+           int             link_type,
+           int             replace_partial_links)
+{
+    int flags_in;
+    u_int start_point;
+    struct alias_link *link;
+    struct alias_link *link_fully_specified;
+    struct alias_link *link_unknown_all;
+    struct alias_link *link_unknown_dst_addr;
+    struct alias_link *link_unknown_dst_port;
+
+/* Initialize pointers */
+    link_fully_specified  = NULL;
+    link_unknown_all      = NULL;
+    link_unknown_dst_addr = NULL;
+    link_unknown_dst_port = NULL;
+
+/* If either the dest addr or port is unknown, the search
+   loop will have to know about this. */
+
+    flags_in = 0;
+    if (dst_addr.s_addr == 0)
+        flags_in |= LINK_UNKNOWN_DEST_ADDR;
+    if (dst_port == 0)
+        flags_in |= LINK_UNKNOWN_DEST_PORT;
+
+/* The following allows permanent links to be
+   be specified as using the default aliasing address
+   (i.e. device interface address) without knowing
+   in advance what that address is. */
+
+    if (alias_addr.s_addr == aliasAddress.s_addr)
+        alias_addr.s_addr = 0;
+
+/* Search loop */
+    start_point = StartPointIn(alias_addr, alias_port, link_type);
+    link = linkTableIn[start_point];
+    while (link != NULL)
+    {
+        int flags;
+
+        flags = flags_in | link->flags;
+        if (!(flags & LINK_PARTIALLY_SPECIFIED))
+        {
+            if (link->alias_addr.s_addr == alias_addr.s_addr
+             && link->alias_port        == alias_port 
+             && link->dst_addr.s_addr   == dst_addr.s_addr
+             && link->dst_port          == dst_port
+             && link->link_type         == link_type)
+            {
+                link_fully_specified = link;
+                break;
+            }
+        }
+        else if ((flags & LINK_UNKNOWN_DEST_ADDR)
+              && (flags & LINK_UNKNOWN_DEST_PORT))
+        {
+            if (link->alias_addr.s_addr == alias_addr.s_addr
+             && link->alias_port        == alias_port
+             && link->link_type         == link_type)
+            {
+                if (link_unknown_all == NULL)
+                    link_unknown_all = link;
+            }
+        }
+        else if (flags & LINK_UNKNOWN_DEST_ADDR)
+        {
+            if (link->alias_addr.s_addr == alias_addr.s_addr
+             && link->alias_port        == alias_port
+             && link->link_type         == link_type
+             && link->dst_port          == dst_port)
+            {
+                if (link_unknown_dst_addr == NULL)
+                    link_unknown_dst_addr = link;
+            }
+        }
+        else if (flags & LINK_UNKNOWN_DEST_PORT)
+        {
+            if (link->alias_addr.s_addr == alias_addr.s_addr
+             && link->alias_port        == alias_port
+             && link->link_type         == link_type
+             && link->dst_addr.s_addr   == dst_addr.s_addr)
+            {
+                if (link_unknown_dst_port == NULL)
+                    link_unknown_dst_port = link;
+            }
+        }
+        link = link->next_in;
+    }
+
+
+
+    if (link_fully_specified != NULL)
+    {
+        return link_fully_specified;
+    }
+    else if (link_unknown_dst_port != NULL)
+    {
+        return replace_partial_links
+          ? ReLink(link_unknown_dst_port,
+                   link_unknown_dst_port->src_addr, dst_addr, alias_addr,
+                   link_unknown_dst_port->src_port, dst_port, alias_port,
+                   link_type)
+          : link_unknown_dst_port;
+    }
+    else if (link_unknown_dst_addr != NULL)
+    {
+        return replace_partial_links
+          ? ReLink(link_unknown_dst_addr,
+                   link_unknown_dst_addr->src_addr, dst_addr, alias_addr,
+                   link_unknown_dst_addr->src_port, dst_port, alias_port,
+                   link_type)
+          : link_unknown_dst_addr;
+    }
+    else if (link_unknown_all != NULL)
+    {
+        return replace_partial_links
+          ? ReLink(link_unknown_all,
+                   link_unknown_all->src_addr, dst_addr, alias_addr,
+                   link_unknown_all->src_port, dst_port, alias_port,
+                   link_type)
+          : link_unknown_all;
+    }
+    else
+    {
+        return(NULL);
+    }
+}
+
+
+
+
+/* External routines for finding/adding links
+
+-- "external" means outside alias_db.c, but within alias*.c --
+
+    FindIcmpIn(), FindIcmpOut()
+    FindFragmentIn1(), FindFragmentIn2()
+    AddFragmentPtrLink(), FindFragmentPtr()
+    FindUdpTcpIn(), FindUdpTcpOut()
+    FindOriginalAddress(), FindAliasAddress()
+
+(prototypes in alias_local.h)
+*/
+
+
+struct alias_link *
+FindIcmpIn(struct in_addr dst_addr,
+           struct in_addr alias_addr,
+           u_short id_alias)
+{
+    return FindLinkIn(dst_addr, alias_addr,
+                      NO_DEST_PORT, id_alias,
+                      LINK_ICMP, 0);
+}
+
+
+struct alias_link *
+FindIcmpOut(struct in_addr src_addr,
+            struct in_addr dst_addr,
+            u_short id)
+{
+    struct alias_link * link;
+
+    link = FindLinkOut(src_addr, dst_addr,
+                       id, NO_DEST_PORT,
+                       LINK_ICMP);
+    if (link == NULL)
+    {
+        struct in_addr alias_addr;
+
+        alias_addr = FindAliasAddress(src_addr);
+        link = AddLink(src_addr, dst_addr, alias_addr,
+                       id, NO_DEST_PORT, GET_ALIAS_ID,
+                       LINK_ICMP);
+    }
+
+    return(link);
+}
+
+
+struct alias_link *
+FindFragmentIn1(struct in_addr dst_addr,
+                struct in_addr alias_addr,
+                u_short ip_id)
+{
+    struct alias_link *link;
+
+    link = FindLinkIn(dst_addr, alias_addr,
+                      NO_DEST_PORT, ip_id,
+                      LINK_FRAGMENT_ID, 0);
+
+    if (link == NULL)
+    {
+        link = AddLink(nullAddress, dst_addr, alias_addr,
+                       NO_SRC_PORT, NO_DEST_PORT, ip_id,
+                       LINK_FRAGMENT_ID);
+    }
+
+    return(link);
+}
+
+
+struct alias_link *
+FindFragmentIn2(struct in_addr dst_addr,   /* Doesn't add a link if one */
+                struct in_addr alias_addr, /*   is not found.           */
+                u_short ip_id)
+{
+    return FindLinkIn(dst_addr, alias_addr,
+                      NO_DEST_PORT, ip_id,
+                      LINK_FRAGMENT_ID, 0);
+}
+
+
+struct alias_link *
+AddFragmentPtrLink(struct in_addr dst_addr,
+                   u_short ip_id)
+{
+    return AddLink(nullAddress, dst_addr, nullAddress,
+                   NO_SRC_PORT, NO_DEST_PORT, ip_id,
+                   LINK_FRAGMENT_PTR);
+}
+
+
+struct alias_link *
+FindFragmentPtr(struct in_addr dst_addr,
+                u_short ip_id)
+{
+    return FindLinkIn(dst_addr, nullAddress,
+                      NO_DEST_PORT, ip_id,
+                      LINK_FRAGMENT_PTR, 0);
+}
+
+
+struct alias_link *
+FindUdpTcpIn(struct in_addr dst_addr,
+             struct in_addr alias_addr,
+             u_short        dst_port,
+             u_short        alias_port,
+             u_char         proto)
+{
+    int link_type;
+    struct alias_link *link;
+
+    switch (proto)
+    {
+    case IPPROTO_UDP:
+        link_type = LINK_UDP;
+        break;
+    case IPPROTO_TCP:
+        link_type = LINK_TCP;
+        break;
+    default:
+        return NULL;
+        break;
+    }
+
+    link = FindLinkIn(dst_addr, alias_addr,
+                      dst_port, alias_port,
+                      link_type, 1);
+
+    if (!(packetAliasMode & PKT_ALIAS_DENY_INCOMING)
+     && !(packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+     && link == NULL)
+    {
+        struct in_addr target_addr;
+
+        target_addr = FindOriginalAddress(alias_addr);
+        link = AddLink(target_addr, dst_addr, alias_addr,
+                       alias_port, dst_port, alias_port,
+                       link_type);
+    }
+
+    return(link);
+}
+
+
+struct alias_link * 
+FindUdpTcpOut(struct in_addr  src_addr,
+              struct in_addr  dst_addr,
+              u_short         src_port,
+              u_short         dst_port,
+              u_char          proto)
+{
+    int link_type;
+    struct alias_link *link;
+
+    switch (proto)
+    {
+    case IPPROTO_UDP:
+        link_type = LINK_UDP;
+        break;
+    case IPPROTO_TCP:
+        link_type = LINK_TCP;
+        break;
+    default:
+        return NULL;
+        break;
+    }
+
+    link = FindLinkOut(src_addr, dst_addr, src_port, dst_port, link_type);
+
+    if (link == NULL)
+    {
+        struct in_addr alias_addr;
+
+        alias_addr = FindAliasAddress(src_addr);
+        link = AddLink(src_addr, dst_addr, alias_addr,
+                       src_port, dst_port, GET_ALIAS_PORT,
+                       link_type);
+    }
+
+    return(link);
+}
+
+
+struct in_addr
+FindOriginalAddress(struct in_addr alias_addr)
+{
+    struct alias_link *link;
+    
+    link = FindLinkIn(nullAddress, alias_addr,
+                      0, 0, LINK_ADDR, 0);
+    if (link == NULL)
+    {
+        newDefaultLink = 1;
+        if (targetAddress.s_addr != 0)
+            return targetAddress;
+        else
+            return alias_addr;
+    }
+    else
+    {
+        if (link->src_addr.s_addr == 0)
+            return aliasAddress;
+        else
+            return link->src_addr;
+    }
+}
+
+
+struct in_addr
+FindAliasAddress(struct in_addr original_addr)
+{
+    struct alias_link *link;
+    
+    link = FindLinkOut(original_addr, nullAddress,
+                       0, 0, LINK_ADDR);
+    if (link == NULL)
+    {
+        return aliasAddress;
+    }
+    else
+    {
+        if (link->alias_addr.s_addr == 0)
+            return aliasAddress;
+        else
+            return link->alias_addr;
+    }
+}
+
+
+/* External routines for getting or changing link data
+   (external to alias_db.c, but internal to alias*.c)
+
+    SetFragmentData(), GetFragmentData()
+    SetFragmentPtr(), GetFragmentPtr()
+    SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
+    GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
+    GetOriginalPort(), GetAliasPort()
+    SetAckModified(), GetAckModified()
+    GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
+*/
+
+
+void
+SetFragmentAddr(struct alias_link *link, struct in_addr src_addr)
+{
+    link->data.frag_addr = src_addr;
+}
+
+
+void
+GetFragmentAddr(struct alias_link *link, struct in_addr *src_addr)
+{
+    *src_addr = link->data.frag_addr;
+}
+
+
+void
+SetFragmentPtr(struct alias_link *link, char *fptr)
+{
+    link->data.frag_ptr = fptr;
+}
+
+
+void
+GetFragmentPtr(struct alias_link *link, char **fptr)
+{
+   *fptr = link->data.frag_ptr;
+}
+
+
+void
+SetStateIn(struct alias_link *link, int state)
+{
+    /* TCP input state */
+    switch (state) {
+    case ALIAS_TCP_STATE_DISCONNECTED:
+        if (link->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) {
+            link->expire_time = TCP_EXPIRE_DEAD;
+        } else {
+            link->expire_time = TCP_EXPIRE_SINGLEDEAD;
+        }
+        link->data.tcp->state.in = state;
+        break;
+    case ALIAS_TCP_STATE_CONNECTED:
+        link->expire_time = TCP_EXPIRE_CONNECTED;
+        /*FALLTHROUGH*/
+    case ALIAS_TCP_STATE_NOT_CONNECTED:
+        link->data.tcp->state.in = state;
+        break;
+    default:
+        abort();
+    }
+}
+
+
+void
+SetStateOut(struct alias_link *link, int state)
+{
+    /* TCP output state */
+    switch (state) {
+    case ALIAS_TCP_STATE_DISCONNECTED:
+        if (link->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) {
+            link->expire_time = TCP_EXPIRE_DEAD;
+        } else {
+            link->expire_time = TCP_EXPIRE_SINGLEDEAD;
+        }
+        link->data.tcp->state.out = state;
+        break;
+    case ALIAS_TCP_STATE_CONNECTED:
+        link->expire_time = TCP_EXPIRE_CONNECTED;
+        /*FALLTHROUGH*/
+    case ALIAS_TCP_STATE_NOT_CONNECTED:
+        link->data.tcp->state.out = state;
+        break;
+    default:
+        abort();
+    }
+}
+
+
+int
+GetStateIn(struct alias_link *link)
+{
+    /* TCP input state */
+    return link->data.tcp->state.in;
+}
+
+
+int
+GetStateOut(struct alias_link *link)
+{
+    /* TCP output state */
+    return link->data.tcp->state.out;
+}
+
+
+struct in_addr
+GetOriginalAddress(struct alias_link *link)
+{
+    if (link->src_addr.s_addr == 0)
+        return aliasAddress;
+    else
+        return(link->src_addr);
+}
+
+
+struct in_addr
+GetDestAddress(struct alias_link *link)
+{
+    return(link->dst_addr);
+}
+
+
+struct in_addr
+GetAliasAddress(struct alias_link *link)
+{
+    if (link->alias_addr.s_addr == 0)
+        return aliasAddress;
+    else
+        return link->alias_addr;
+}
+
+
+struct in_addr
+GetDefaultAliasAddress()
+{
+    return aliasAddress;
+}
+
+
+void
+SetDefaultAliasAddress(struct in_addr alias_addr)
+{
+    aliasAddress = alias_addr;
+}
+
+
+u_short
+GetOriginalPort(struct alias_link *link)
+{
+    return(link->src_port);
+}
+
+
+u_short
+GetAliasPort(struct alias_link *link)
+{
+    return(link->alias_port);
+}
+
+u_short
+GetDestPort(struct alias_link *link)
+{
+    return(link->dst_port);
+}
+
+void
+SetAckModified(struct alias_link *link)
+{
+/* Indicate that ack numbers have been modified in a TCP connection */
+    link->data.tcp->state.ack_modified = 1;
+}
+
+
+struct in_addr
+GetProxyAddress(struct alias_link *link)
+{
+    return link->proxy_addr;
+}
+
+
+void
+SetProxyAddress(struct alias_link *link, struct in_addr addr)
+{
+    link->proxy_addr = addr;
+}
+
+
+u_short
+GetProxyPort(struct alias_link *link)
+{
+    return link->proxy_port;
+}
+
+
+void
+SetProxyPort(struct alias_link *link, u_short port)
+{
+    link->proxy_port = port;
+}
+
+
+int
+GetAckModified(struct alias_link *link)
+{
+/* See if ack numbers have been modified */
+    return link->data.tcp->state.ack_modified;
+}
+
+
+int
+GetDeltaAckIn(struct ip *pip, struct alias_link *link)
+{
+/*
+Find out how much the ack number has been altered for an incoming
+TCP packet.  To do this, a circular list is ack numbers where the TCP
+packet size was altered is searched. 
+*/
+
+    int i;
+    struct tcphdr *tc;
+    int delta, ack_diff_min;
+    u_long ack;
+
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+    ack      = tc->th_ack;
+
+    delta = 0;
+    ack_diff_min = -1;
+    for (i=0; i<N_LINK_TCP_DATA; i++)
+    {
+        struct ack_data_record x;
+
+        x = link->data.tcp->ack[i];
+        if (x.active == 1)
+        {
+            int ack_diff;
+
+            ack_diff = SeqDiff(x.ack_new, ack);
+            if (ack_diff >= 0)
+            {
+                if (ack_diff_min >= 0)
+                {
+                    if (ack_diff < ack_diff_min)
+                    {
+                        delta = x.delta;
+                        ack_diff_min = ack_diff;
+                    }
+                }
+                else
+                {
+                    delta = x.delta;
+                    ack_diff_min = ack_diff;
+                }
+            }
+        }
+    }
+    return (delta);
+}
+
+
+int
+GetDeltaSeqOut(struct ip *pip, struct alias_link *link)
+{
+/*
+Find out how much the seq number has been altered for an outgoing
+TCP packet.  To do this, a circular list is ack numbers where the TCP
+packet size was altered is searched. 
+*/
+
+    int i;
+    struct tcphdr *tc;
+    int delta, seq_diff_min;
+    u_long seq;
+
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+    seq = tc->th_seq;
+
+    delta = 0;
+    seq_diff_min = -1;
+    for (i=0; i<N_LINK_TCP_DATA; i++)
+    {
+        struct ack_data_record x;
+
+        x = link->data.tcp->ack[i];
+        if (x.active == 1)
+        {
+            int seq_diff;
+
+            seq_diff = SeqDiff(x.ack_old, seq);
+            if (seq_diff >= 0)
+            {
+                if (seq_diff_min >= 0)
+                {
+                    if (seq_diff < seq_diff_min)
+                    {
+                        delta = x.delta;
+                        seq_diff_min = seq_diff;
+                    }
+                }
+                else
+                {
+                    delta = x.delta;
+                    seq_diff_min = seq_diff;
+                }
+            }
+        }
+    }
+    return (delta);
+}
+
+
+void
+AddSeq(struct ip *pip, struct alias_link *link, int delta)
+{
+/*
+When a TCP packet has been altered in length, save this
+information in a circular list.  If enough packets have
+been altered, then this list will begin to overwrite itself.
+*/
+
+    struct tcphdr *tc;
+    struct ack_data_record x;
+    int hlen, tlen, dlen;
+    int i;
+
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+    hlen = (pip->ip_hl + tc->th_off) << 2;
+    tlen = ntohs(pip->ip_len);
+    dlen = tlen - hlen;
+
+    x.ack_old = htonl(ntohl(tc->th_seq) + dlen);
+    x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta);
+    x.delta = delta;
+    x.active = 1;
+
+    i = link->data.tcp->state.index;
+    link->data.tcp->ack[i] = x;
+
+    i++;
+    if (i == N_LINK_TCP_DATA)
+        link->data.tcp->state.index = 0;
+    else
+        link->data.tcp->state.index = i;
+}
+
+void
+SetExpire(struct alias_link *link, int expire)
+{
+    if (expire == 0)
+    {
+        link->flags &= ~LINK_PERMANENT;
+        DeleteLink(link);
+    }
+    else if (expire == -1)
+    {
+        link->flags |= LINK_PERMANENT;
+    }
+    else if (expire > 0)
+    {
+        link->expire_time = expire;
+    }
+    else
+    {
+#ifdef DEBUG
+        fprintf(stderr, "PacketAlias/SetExpire(): ");
+        fprintf(stderr, "error in expire parameter\n");
+#endif
+    }
+}
+
+void
+ClearCheckNewLink(void)
+{
+    newDefaultLink = 0;
+}
+
+
+/* Miscellaneous Functions
+
+    HouseKeeping()
+    InitPacketAliasLog()
+    UninitPacketAliasLog()
+*/
+
+/*
+    Whenever an outgoing or incoming packet is handled, HouseKeeping()
+    is called to find and remove timed-out aliasing links.  Logic exists
+    to sweep through the entire table and linked list structure
+    every 60 seconds.
+
+    (prototype in alias_local.h)
+*/
+
+void
+HouseKeeping(void)
+{
+    int i, n, n100;
+    struct timeval tv;
+    struct timezone tz;
+
+    /*
+     * Save system time (seconds) in global variable timeStamp for
+     * use by other functions. This is done so as not to unnecessarily
+     * waste timeline by making system calls.
+     */
+    gettimeofday(&tv, &tz);
+    timeStamp = tv.tv_sec;
+
+    /* Compute number of spokes (output table link chains) to cover */
+    n100  = LINK_TABLE_OUT_SIZE * 100 + houseKeepingResidual;
+    n100 *= timeStamp - lastCleanupTime;
+    n100 /= ALIAS_CLEANUP_INTERVAL_SECS;
+
+    n = n100/100;
+
+    /* Handle different cases */
+    if (n > ALIAS_CLEANUP_MAX_SPOKES)
+    {
+        n = ALIAS_CLEANUP_MAX_SPOKES;
+        lastCleanupTime = timeStamp;
+        houseKeepingResidual = 0;
+
+        for (i=0; i<n; i++)
+            IncrementalCleanup();
+    }
+    else if (n > 0)
+    {
+        lastCleanupTime = timeStamp;
+        houseKeepingResidual = n100 - 100*n;
+
+        for (i=0; i<n; i++)
+            IncrementalCleanup();
+    }
+    else if (n < 0)
+    {
+#ifdef DEBUG
+        fprintf(stderr, "PacketAlias/HouseKeeping(): ");
+        fprintf(stderr, "something unexpected in time values\n");
+#endif
+        lastCleanupTime = timeStamp;
+        houseKeepingResidual = 0;
+    }
+}
+
+
+/* Init the log file and enable logging */
+static void
+InitPacketAliasLog(void)
+{
+   if ((~packetAliasMode & PKT_ALIAS_LOG)
+    && (monitorFile = fopen("/var/log/alias.log", "w")))
+   {
+      packetAliasMode |= PKT_ALIAS_LOG;
+      fprintf(monitorFile,
+      "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
+   }
+}
+
+
+/* Close the log-file and disable logging. */
+static void
+UninitPacketAliasLog(void)
+{
+    if (monitorFile) {
+        fclose(monitorFile);
+        monitorFile = NULL;
+    }
+    packetAliasMode &= ~PKT_ALIAS_LOG;
+}
+
+
+
+
+
+
+/* Outside world interfaces
+
+-- "outside world" means other than alias*.c routines --
+
+    PacketAliasRedirectPort()
+    PacketAliasRedirectAddr()
+    PacketAliasRedirectDelete()
+    PacketAliasSetAddress()
+    PacketAliasInit()
+    PacketAliasUninit()
+    PacketAliasSetMode()
+
+(prototypes in alias.h)
+*/
+
+/* Redirection from a specific public addr:port to a
+   a private addr:port */
+struct alias_link *
+PacketAliasRedirectPort(struct in_addr src_addr,   u_short src_port,
+                        struct in_addr dst_addr,   u_short dst_port,
+                        struct in_addr alias_addr, u_short alias_port,
+                        u_char proto)
+{
+    int link_type;
+    struct alias_link *link;
+
+    switch(proto)
+    {
+    case IPPROTO_UDP:
+        link_type = LINK_UDP;
+        break;
+    case IPPROTO_TCP:
+        link_type = LINK_TCP;
+        break;
+    default:
+#ifdef DEBUG
+        fprintf(stderr, "PacketAliasRedirectPort(): ");
+        fprintf(stderr, "only TCP and UDP protocols allowed\n");
+#endif
+        return NULL;
+    }
+
+    link = AddLink(src_addr, dst_addr, alias_addr,
+                   src_port, dst_port, alias_port,
+                   link_type);
+
+    if (link != NULL)
+    {
+        link->flags |= LINK_PERMANENT;
+    }
+#ifdef DEBUG
+    else
+    {
+        fprintf(stderr, "PacketAliasRedirectPort(): " 
+                        "call to AddLink() failed\n");
+    }
+#endif
+
+    return link;
+}
+
+/* Translate PPTP packets to a machine on the inside
+ */
+int
+PacketAliasPptp(struct in_addr src_addr)
+{
+
+    pptpAliasAddr = src_addr;          /* Address of the inside PPTP machine */
+    pptpAliasFlag = src_addr.s_addr != INADDR_NONE;
+
+    return 1;
+}
+
+int GetPptpAlias (struct in_addr* alias_addr)
+{
+    if (pptpAliasFlag)
+       *alias_addr = pptpAliasAddr;
+
+    return pptpAliasFlag;
+}
+
+/* Static address translation */
+struct alias_link *
+PacketAliasRedirectAddr(struct in_addr src_addr,
+                        struct in_addr alias_addr)
+{
+    struct alias_link *link;
+
+    link = AddLink(src_addr, nullAddress, alias_addr,
+                   0, 0, 0,
+                   LINK_ADDR);
+
+    if (link != NULL)
+    {
+        link->flags |= LINK_PERMANENT;
+    }
+#ifdef DEBUG
+    else
+    {
+        fprintf(stderr, "PacketAliasRedirectAddr(): " 
+                        "call to AddLink() failed\n");
+    }
+#endif
+
+    return link;
+}
+
+
+void
+PacketAliasRedirectDelete(struct alias_link *link)
+{
+/* This is a dangerous function to put in the API,
+   because an invalid pointer can crash the program. */
+
+    deleteAllLinks = 1;
+    DeleteLink(link);
+    deleteAllLinks = 0;
+}
+
+
+void
+PacketAliasSetAddress(struct in_addr addr)
+{
+    if (packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE
+     && aliasAddress.s_addr != addr.s_addr)
+        CleanupAliasData();
+
+    aliasAddress = addr;
+}
+
+
+void
+PacketAliasSetTarget(struct in_addr target_addr)
+{
+    targetAddress = target_addr;
+}
+
+
+void
+PacketAliasInit(void)
+{
+    int i;
+    struct timeval tv;
+    struct timezone tz;
+    static int firstCall = 1;
+
+    if (firstCall == 1)
+    {
+        gettimeofday(&tv, &tz);
+        timeStamp = tv.tv_sec;
+        lastCleanupTime = tv.tv_sec;
+        houseKeepingResidual = 0;
+
+        for (i=0; i<LINK_TABLE_OUT_SIZE; i++)
+            linkTableOut[i] = NULL;
+        for (i=0; i<LINK_TABLE_IN_SIZE; i++)
+            linkTableIn[i] = NULL;
+
+        atexit(PacketAliasUninit);
+        firstCall = 0;
+    }
+    else
+    {
+        deleteAllLinks = 1;
+        CleanupAliasData();
+        deleteAllLinks = 0;
+    }
+
+    aliasAddress.s_addr = 0;
+    targetAddress.s_addr = 0;
+
+    icmpLinkCount = 0;
+    udpLinkCount = 0;
+    tcpLinkCount = 0;
+    fragmentIdLinkCount = 0;
+    fragmentPtrLinkCount = 0;
+    sockCount = 0;
+
+    cleanupIndex =0;
+
+    packetAliasMode = PKT_ALIAS_SAME_PORTS
+                    | PKT_ALIAS_USE_SOCKETS
+                    | PKT_ALIAS_RESET_ON_ADDR_CHANGE;
+
+    pptpAliasFlag = 0;
+}
+
+void
+PacketAliasUninit(void) {
+    deleteAllLinks = 1;
+    CleanupAliasData();
+    deleteAllLinks = 0;
+    UninitPacketAliasLog();
+#ifndef NO_FW_PUNCH
+    UninitPunchFW();
+#endif
+}
+
+
+/* Change mode for some operations */
+unsigned int
+PacketAliasSetMode(
+    unsigned int flags, /* Which state to bring flags to */
+    unsigned int mask   /* Mask of which flags to affect (use 0 to do a
+                           probe for flag values) */
+)
+{
+/* Enable logging? */
+    if (flags & mask & PKT_ALIAS_LOG)
+    {
+        InitPacketAliasLog();     /* Do the enable */
+    } else
+/* _Disable_ logging? */
+    if (~flags & mask & PKT_ALIAS_LOG) {
+        UninitPacketAliasLog();
+    }
+
+#ifndef NO_FW_PUNCH
+/* Start punching holes in the firewall? */
+    if (flags & mask & PKT_ALIAS_PUNCH_FW) {
+        InitPunchFW();
+    } else
+/* Stop punching holes in the firewall? */
+    if (~flags & mask & PKT_ALIAS_PUNCH_FW) {
+        UninitPunchFW();
+    }
+#endif
+
+/* Other flags can be set/cleared without special action */
+    packetAliasMode = (flags & mask) | (packetAliasMode & ~mask);
+    return packetAliasMode;
+}
+
+
+int
+PacketAliasCheckNewLink(void)
+{
+    return newDefaultLink;
+}
+
+
+#ifndef NO_FW_PUNCH
+
+/*****************
+  Code to support firewall punching.  This shouldn't really be in this
+  file, but making variables global is evil too.
+  ****************/
+
+/* Firewall include files */
+#include <sys/queue.h>
+#include <net/if.h>
+#include <netinet/ip_fw.h>
+#include <string.h>
+#include <err.h>
+
+static void ClearAllFWHoles(void);
+
+static int fireWallBaseNum;     /* The first firewall entry free for our use */
+static int fireWallNumNums;     /* How many entries can we use? */
+static int fireWallActiveNum;   /* Which entry did we last use? */
+static char *fireWallField;     /* bool array for entries */
+
+#define fw_setfield(field, num)                         \
+do {                                                    \
+    (field)[num] = 1;                                   \
+} /*lint -save -e717 */ while(0) /*lint -restore */
+#define fw_clrfield(field, num)                         \
+do {                                                    \
+    (field)[num] = 0;                                   \
+} /*lint -save -e717 */ while(0) /*lint -restore */
+#define fw_tstfield(field, num) ((field)[num])
+
+void
+PacketAliasSetFWBase(unsigned int base, unsigned int num) {
+    fireWallBaseNum = base;
+    fireWallNumNums = num;
+}
+
+static void
+InitPunchFW(void) {
+    fireWallField = malloc(fireWallNumNums);
+    if (fireWallField) {
+        memset(fireWallField, 0, fireWallNumNums);
+        if (fireWallFD < 0) {
+            fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+        }
+        ClearAllFWHoles();
+        fireWallActiveNum = fireWallBaseNum;
+    }
+}
+
+static void
+UninitPunchFW(void) {
+    ClearAllFWHoles();
+    if (fireWallFD >= 0)
+        close(fireWallFD);
+    fireWallFD = -1;
+    if (fireWallField)
+        free(fireWallField);
+    fireWallField = NULL;
+    packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
+}
+
+/* Make a certain link go through the firewall */
+void
+PunchFWHole(struct alias_link *link) {
+    int r;                      /* Result code */
+    struct ip_fw rule;          /* On-the-fly built rule */
+    int fwhole;                 /* Where to punch hole */
+
+/* Don't do anything unless we are asked to */
+    if ( !(packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
+         fireWallFD < 0 ||
+         link->link_type != LINK_TCP ||
+         !link->data.tcp)
+        return;
+
+    memset(&rule, 0, sizeof rule);
+
+/** Build rule **/
+
+    /* Find empty slot */
+    for (fwhole = fireWallActiveNum;
+         fwhole < fireWallBaseNum + fireWallNumNums &&
+             fw_tstfield(fireWallField, fwhole);
+         fwhole++)
+        ;
+    if (fwhole >= fireWallBaseNum + fireWallNumNums ||
+        fw_tstfield(fireWallField, fwhole)) {
+        for (fwhole = fireWallBaseNum;
+             fwhole < fireWallActiveNum &&
+                 fw_tstfield(fireWallField, fwhole);
+             fwhole++)
+            ;
+        if (fwhole == fireWallActiveNum) {
+            /* No rule point empty - we can't punch more holes. */
+            fireWallActiveNum = fireWallBaseNum;
+#ifdef DEBUG
+            fprintf(stderr, "libalias: Unable to create firewall hole!\n");
+#endif
+            return;
+        }
+    }
+    /* Start next search at next position */
+    fireWallActiveNum = fwhole+1;
+
+    /* Build generic part of the two rules */
+    rule.fw_number = fwhole;
+    rule.fw_nports = 1;         /* Number of source ports; dest ports follow */
+    rule.fw_flg = IP_FW_F_ACCEPT;
+    rule.fw_prot = IPPROTO_TCP;
+    rule.fw_smsk.s_addr = INADDR_BROADCAST;
+    rule.fw_dmsk.s_addr = INADDR_BROADCAST;
+
+    /* Build and apply specific part of the rules */
+    rule.fw_src = GetOriginalAddress(link);
+    rule.fw_dst = GetDestAddress(link);
+    rule.fw_uar.fw_pts[0] = ntohs(GetOriginalPort(link));
+    rule.fw_uar.fw_pts[1] = ntohs(GetDestPort(link));
+
+    /* Skip non-bound links - XXX should not be strictly necessary,
+       but seems to leave hole if not done.  Leak of non-bound links?
+       (Code should be left even if the problem is fixed - it is a
+       clear optimization) */
+    if (rule.fw_uar.fw_pts[0] != 0 && rule.fw_uar.fw_pts[1] != 0) {
+        r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
+#ifdef DEBUG
+        if (r)
+            err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
+#endif
+        rule.fw_src = GetDestAddress(link);
+        rule.fw_dst = GetOriginalAddress(link);
+        rule.fw_uar.fw_pts[0] = ntohs(GetDestPort(link));
+        rule.fw_uar.fw_pts[1] = ntohs(GetOriginalPort(link));
+        r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
+#ifdef DEBUG
+        if (r)
+            err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
+#endif
+    }
+/* Indicate hole applied */
+    link->data.tcp->fwhole = fwhole;
+    fw_setfield(fireWallField, fwhole);
+}
+
+/* Remove a hole in a firewall associated with a particular alias
+   link.  Calling this too often is harmless. */
+static void
+ClearFWHole(struct alias_link *link) {
+    if (link->link_type == LINK_TCP && link->data.tcp) {
+        int fwhole =  link->data.tcp->fwhole; /* Where is the firewall hole? */
+        struct ip_fw rule;
+
+        if (fwhole < 0)
+            return;
+
+        memset(&rule, 0, sizeof rule);
+        rule.fw_number = fwhole;
+        while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
+            ;
+        fw_clrfield(fireWallField, fwhole);
+        link->data.tcp->fwhole = -1;
+    }
+}
+
+/* Clear out the entire range dedicated to firewall holes. */
+static void
+ClearAllFWHoles(void) {
+    struct ip_fw rule;          /* On-the-fly built rule */
+    int i;
+    
+    if (fireWallFD < 0)
+        return;
+
+    memset(&rule, 0, sizeof rule);
+    for (i = fireWallBaseNum; i < fireWallBaseNum + fireWallNumNums; i++) {
+        rule.fw_number = i;
+        while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule))
+            ;
+    }
+    memset(fireWallField, 0, fireWallNumNums);
+}
+#endif
diff --git a/alias/alias_ftp.c b/alias/alias_ftp.c
new file mode 100644 (file)
index 0000000..73769fd
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+    Alias_ftp.c performs special processing for FTP sessions under
+    TCP.  Specifically, when a PORT command from the client side
+    is sent, it is intercepted and modified.  The address is changed
+    to the gateway machine and an aliasing port is used.
+
+    For this routine to work, the PORT command must fit entirely
+    into a single TCP packet.  This is typically the case, but exceptions
+    can easily be envisioned under the actual specifications.
+
+    Probably the most troubling aspect of the approach taken here is
+    that the new PORT command will typically be a different length, and
+    this causes a certain amount of bookkeeping to keep track of the
+    changes of sequence and acknowledgment numbers, since the client
+    machine is totally unaware of the modification to the TCP stream.
+
+
+    This software is placed into the public domain with no restrictions
+    on its distribution.
+
+    Initial version:  August, 1996  (cjm)
+
+    Version 1.6
+         Brian Somers and Martin Renters identified an IP checksum
+         error for modified IP packets.
+
+    Version 1.7:  January 9, 1996 (cjm)
+         Differental checksum computation for change
+         in IP packet length.
+   
+    Version 2.1:  May, 1997 (cjm)
+         Very minor changes to conform with
+         local/global/function naming conventions
+         withing the packet alising module.
+
+    See HISTORY file for record of revisions.
+*/
+
+/* Includes */
+#include <ctype.h>
+#include <stdio.h> 
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "alias_local.h"
+
+static void NewFtpPortCommand(struct ip *, struct alias_link *, struct in_addr, u_short, int);
+
+
+
+void
+AliasHandleFtpOut(
+struct ip *pip,          /* IP packet to examine/patch */
+struct alias_link *link, /* The link to go through (aliased port) */
+int maxpacketsize  /* The maximum size this packet can grow to (including headers) */)
+{
+    int hlen, tlen, dlen;
+    struct in_addr true_addr;
+    u_short true_port;
+    char *sptr;
+    struct tcphdr *tc;
+        
+/* Calculate data length of TCP packet */
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+    hlen = (pip->ip_hl + tc->th_off) << 2;
+    tlen = ntohs(pip->ip_len);
+    dlen = tlen - hlen;
+
+/* Return is data length is too long or too short */
+    if (dlen<10 || dlen>80)
+        return;
+
+/* Place string pointer and beginning of data */
+    sptr = (char *) pip;  
+    sptr += hlen;
+
+/* Parse through string using state diagram method */
+    {
+        char ch, zero;
+        int i, state;
+        u_long a1, a2, a3, a4;
+        u_short p1, p2; 
+
+        a1=0; a2=0; a3=0; a4=0; p1=0; p2=0;
+        zero = '0';
+        state=-4;
+        for (i=0; i<dlen; i++)
+        {
+            ch = sptr[i];
+            switch (state)
+            {
+                case -4: if (ch == 'P') state=-3; else return; break;
+                case -3: if (ch == 'O') state=-2; else return; break;
+                case -2: if (ch == 'R') state=-1; else return; break;
+                case -1: if (ch == 'T') state= 0; else return; break;
+
+                case 0 :
+                    if (isdigit(ch)) {a1=ch-zero; state=1 ;} break;
+                case 1 :
+                    if (isdigit(ch)) a1=10*a1+ch-zero; else state=2 ; break;
+                case 2 :
+                    if (isdigit(ch)) {a2=ch-zero; state=3 ;} break;
+                case 3 :
+                    if (isdigit(ch)) a2=10*a2+ch-zero; else state=4 ; break;
+                case 4 :
+                    if (isdigit(ch)) {a3=ch-zero; state=5 ;} break;
+                case 5 :
+                    if (isdigit(ch)) a3=10*a3+ch-zero; else state=6 ; break;
+                case 6 :
+                    if (isdigit(ch)) {a4=ch-zero; state=7 ;} break;
+                case 7 :
+                    if (isdigit(ch)) a4=10*a4+ch-zero; else state=8 ; break;
+                case 8 :
+                    if (isdigit(ch)) {p1=ch-zero; state=9 ;} break;
+                case 9 :
+                    if (isdigit(ch)) p1=10*p1+ch-zero; else state=10; break;
+                case 10:
+                    if (isdigit(ch)) {p2=ch-zero; state=11;} break;
+                case 11:
+                    if (isdigit(ch)) p2=10*p2+ch-zero; break;
+            }
+        }
+
+        if (state == 11)
+        {
+            true_port = htons((p1<<8) + p2);
+            true_addr.s_addr = htonl((a1<<24) + (a2<<16) +(a3<<8) + a4);
+            NewFtpPortCommand(pip, link, true_addr, true_port, maxpacketsize);
+        }
+    }
+}
+
+static void
+NewFtpPortCommand(struct ip *pip,
+                  struct alias_link *link,
+                  struct in_addr true_addr,
+                  u_short true_port,
+                  int maxpacketsize)
+{ 
+    struct alias_link *ftp_link;
+
+/* Establish link to address and port found in PORT command */
+    ftp_link = FindUdpTcpOut(true_addr, GetDestAddress(link),
+                             true_port, 0, IPPROTO_TCP);
+
+    if (ftp_link != NULL)
+    {
+        int slen, hlen, tlen, dlen;
+        struct tcphdr *tc;
+
+#ifndef NO_FW_PUNCH
+/* Punch hole in firewall */
+        PunchFWHole(ftp_link);
+#endif
+
+/* Calculate data length of TCP packet */
+        tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+        hlen = (pip->ip_hl + tc->th_off) << 2;
+        tlen = ntohs(pip->ip_len);
+        dlen = tlen - hlen;
+
+/* Create new PORT command */
+        {
+            char stemp[80];
+            char *sptr;
+            u_short alias_port;
+            u_char *ptr;
+            int a1, a2, a3, a4, p1, p2; 
+            struct in_addr alias_address;
+        
+/* Decompose alias address into quad format */
+            alias_address = GetAliasAddress(link);
+            ptr = (u_char *) &alias_address.s_addr;
+            a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr;
+
+/* Decompose alias port into pair format */
+            alias_port = GetAliasPort(ftp_link);
+            ptr = (char *) &alias_port;
+            p1 = *ptr++; p2=*ptr;
+
+/* Generate command string */
+            sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
+                     a1,a2,a3,a4,p1,p2);
+
+/* Save string length for IP header modification */
+            slen = strlen(stemp);
+
+/* Copy into IP packet */
+            sptr = (char *) pip; sptr += hlen;
+            strncpy(sptr, stemp, maxpacketsize-hlen);
+        }
+
+/* Save information regarding modified seq and ack numbers */
+        {
+            int delta;
+
+            SetAckModified(link);
+            delta = GetDeltaSeqOut(pip, link);
+            AddSeq(pip, link, delta+slen-dlen);
+        }
+
+/* Revise IP header */
+        {
+            u_short new_len;
+
+            new_len = htons(hlen + slen);
+            DifferentialChecksum(&pip->ip_sum,
+                                 &new_len,
+                                 &pip->ip_len,
+                                 1);
+            pip->ip_len = new_len;
+        }
+
+/* Compute TCP checksum for revised packet */
+        tc->th_sum = 0;
+        tc->th_sum = TcpChecksum(pip);
+    }
+    else
+    {
+#ifdef DEBUG
+        fprintf(stderr,
+        "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");
+#endif
+    }
+}
diff --git a/alias/alias_irc.c b/alias/alias_irc.c
new file mode 100644 (file)
index 0000000..910e934
--- /dev/null
@@ -0,0 +1,316 @@
+/* Alias_irc.c intercepts packages contain IRC CTCP commands, and
+       changes DCC commands to export a port on the aliasing host instead
+       of an aliased host.
+
+    For this routine to work, the DCC command must fit entirely into a
+    single TCP packet.  This will usually happen, but is not
+    guaranteed.
+
+        The interception is likely to change the length of the packet.
+        The handling of this is copied more-or-less verbatim from
+        ftp_alias.c
+
+    This software is placed into the public domain with no restrictions
+    on its distribution.
+
+        Initial version: Eivind Eklund <perhaps@yes.no> (ee) 97-01-29
+
+         Version 2.1:  May, 1997 (cjm)
+             Very minor changes to conform with
+             local/global/function naming conventions
+             withing the packet alising module.
+*/
+
+/* Includes */
+#include <ctype.h>
+#include <stdio.h> 
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <limits.h>
+
+#include "alias_local.h"
+
+/* Local defines */
+#define DBprintf(a)
+
+
+void
+AliasHandleIrcOut(struct ip *pip, /* IP packet to examine */
+                                struct alias_link *link,                 /* Which link are we on? */
+                                int maxsize              /* Maximum size of IP packet including headers */
+                                )
+{       
+    int hlen, tlen, dlen;
+    struct in_addr true_addr;
+    u_short true_port;
+    char *sptr;
+    struct tcphdr *tc;
+        int i;                                                   /* Iterator through the source */
+        
+/* Calculate data length of TCP packet */
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+    hlen = (pip->ip_hl + tc->th_off) << 2;
+    tlen = ntohs(pip->ip_len);
+    dlen = tlen - hlen;
+
+        /* Return if data length is too short - assume an entire PRIVMSG in each packet. */
+    if (dlen<sizeof(":A!a@n.n PRIVMSG A :aDCC 1 1a")-1)
+        return;
+
+/* Place string pointer at beginning of data */
+    sptr = (char *) pip;  
+    sptr += hlen;
+        maxsize -= hlen;                                 /* We're interested in maximum size of data, not packet */
+
+        /* Search for a CTCP command [Note 1] */
+        for(   i=0; i<dlen; i++ ) {
+                if(sptr[i]=='\001')
+                        goto lFOUND_CTCP;
+        }
+        return;                                          /* No CTCP commands in  */
+        /* Handle CTCP commands - the buffer may have to be copied */
+lFOUND_CTCP:
+        {
+                char newpacket[65536];   /* Estimate of maximum packet size :) */
+                int  copyat = i;                         /* Same */
+                int  iCopy = 0;                          /* How much data have we written to copy-back string? */
+                unsigned long org_addr;  /* Original IP address */
+                unsigned short org_port; /* Original source port address */
+        lCTCP_START:
+                if( i >= dlen || iCopy >= sizeof(newpacket) )
+                        goto lPACKET_DONE;
+                newpacket[iCopy++] = sptr[i++];        /* Copy the CTCP start character */
+                /* Start of a CTCP */
+                if( i+4 >= dlen )                /* Too short for DCC */
+                        goto lBAD_CTCP;
+                if( sptr[i+0] != 'D' )
+                        goto lBAD_CTCP;
+                if( sptr[i+1] != 'C' )
+                        goto lBAD_CTCP;
+                if( sptr[i+2] != 'C' )
+                        goto lBAD_CTCP;
+                if( sptr[i+3] != ' ' )
+                        goto lBAD_CTCP;
+                /* We have a DCC command - handle it! */
+                i+= 4;                                           /* Skip "DCC " */
+                if( iCopy+4 > sizeof(newpacket) )
+                        goto lPACKET_DONE;
+                newpacket[iCopy++] = 'D';
+                newpacket[iCopy++] = 'C';
+                newpacket[iCopy++] = 'C';
+                newpacket[iCopy++] = ' ';
+
+                DBprintf(("Found DCC\n"));
+                /* Skip any extra spaces (should not occur according to
+          protocol, but DCC breaks CTCP protocol anyway */
+                while(sptr[i] == ' ') {
+                        if( ++i >= dlen) {
+                                DBprintf(("DCC packet terminated in just spaces\n"));
+                                goto lPACKET_DONE;
+                        }
+                }
+
+                DBprintf(("Transferring command...\n"));
+                while(sptr[i] != ' ') {
+                        newpacket[iCopy++] = sptr[i];
+                        if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
+                                DBprintf(("DCC packet terminated during command\n"));
+                                goto lPACKET_DONE;
+                        }
+                }
+                /* Copy _one_ space */
+                if( i+1 < dlen && iCopy < sizeof(newpacket) )
+                        newpacket[iCopy++] = sptr[i++];
+
+                DBprintf(("Done command - removing spaces\n"));
+                /* Skip any extra spaces (should not occur according to
+          protocol, but DCC breaks CTCP protocol anyway */
+                while(sptr[i] == ' ') {
+                        if( ++i >= dlen ) {
+                                DBprintf(("DCC packet terminated in just spaces (post-command)\n"));
+                                goto lPACKET_DONE;
+                        }
+                }
+
+                DBprintf(("Transferring filename...\n"));
+                while(sptr[i] != ' ') {
+                        newpacket[iCopy++] = sptr[i];
+                        if( ++i >= dlen || iCopy >= sizeof(newpacket) ) {
+                                DBprintf(("DCC packet terminated during filename\n"));
+                                goto lPACKET_DONE;
+                        }
+                }
+                /* Copy _one_ space */
+                if( i+1 < dlen && iCopy < sizeof(newpacket) )
+                        newpacket[iCopy++] = sptr[i++];
+
+                DBprintf(("Done filename - removing spaces\n"));
+                /* Skip any extra spaces (should not occur according to
+          protocol, but DCC breaks CTCP protocol anyway */
+                while(sptr[i] == ' ') {
+                        if( ++i >= dlen ) {
+                                DBprintf(("DCC packet terminated in just spaces (post-filename)\n"));
+                                goto lPACKET_DONE;
+                        }
+                }
+
+                DBprintf(("Fetching IP address\n"));
+                /* Fetch IP address */
+                org_addr = 0;
+                while(i<dlen && isdigit(sptr[i])) {
+                        if( org_addr > ULONG_MAX/10UL )        { /* Terminate on overflow */
+                                DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i]));
+                                goto lBAD_CTCP;
+                        }
+                        org_addr *= 10;
+                        org_addr += sptr[i++]-'0';
+                }
+                DBprintf(("Skipping space\n"));
+                if( i+1 >= dlen || sptr[i] != ' ' ) {
+                        DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i+1, dlen, sptr[i]));
+                        goto lBAD_CTCP;
+                }
+                /* Skip any extra spaces (should not occur according to
+          protocol, but DCC breaks CTCP protocol anyway, so we might
+          as well play it safe */
+                while(sptr[i] == ' ') {
+                        if( ++i >= dlen ) {
+                                DBprintf(("Packet failure - space overflow.\n"));
+                                goto lPACKET_DONE;
+                        }
+                }
+                DBprintf(("Fetching port number\n"));
+                /* Fetch source port */
+                org_port = 0;
+                while(i<dlen && isdigit(sptr[i])) {
+                        if( org_port > 6554 )  { /* Terminate on overflow (65536/10 rounded up*/
+                                DBprintf(("DCC: port number overflow\n"));
+                                goto lBAD_CTCP;
+                        }
+                        org_port *= 10;
+                        org_port += sptr[i++]-'0';
+                }
+                /* Skip illegal addresses (or early termination) */
+                if( i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ') ) {
+                        DBprintf(("Bad port termination\n"));
+                        goto lBAD_CTCP;
+                }
+                DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port));
+
+                /* We've got the address and port - now alias it */
+                {
+                        struct alias_link *dcc_link;
+                        struct in_addr destaddr;
+                        
+
+                        true_port = htons(org_port);
+                        true_addr.s_addr = htonl(org_addr);
+                        destaddr.s_addr = 0;
+
+                        /* Steal the FTP_DATA_PORT - it doesn't really matter, and this
+                                would probably allow it through at least _some_
+                                firewalls. */
+                        dcc_link = FindUdpTcpOut (true_addr,
+                                                                                       destaddr,
+                                                                                  true_port,
+                                                                                       0, IPPROTO_TCP);
+                        DBprintf(("Got a DCC link\n"));
+                        if ( dcc_link ) {
+                                struct in_addr alias_address;  /* Address from aliasing */
+                                u_short alias_port;    /* Port given by aliasing */
+
+#ifndef NO_FW_PUNCH
+                                /* Generate firewall hole as appropriate */
+                                PunchFWHole(dcc_link);
+#endif
+
+                                alias_address = GetAliasAddress(link);
+                                iCopy += snprintf(&newpacket[iCopy],
+                                                                                sizeof(newpacket)-iCopy, 
+                                                                                "%lu ", (u_long)htonl(alias_address.s_addr));
+                                if( iCopy >= sizeof(newpacket) ) { /* Truncated/fit exactly - bad news */
+                                        DBprintf(("DCC constructed packet overflow.\n"));
+                                        goto lBAD_CTCP;
+                                }
+                                alias_port = GetAliasPort(dcc_link);
+                                iCopy += snprintf(&newpacket[iCopy],
+                                                                                sizeof(newpacket)-iCopy, 
+                                                                                "%u", htons(alias_port) );
+                                /* Done - truncated cases will be taken care of by lBAD_CTCP */
+                                DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port));
+                        }
+                }
+                /* An uninteresting CTCP - state entered right after '\001' has
+          been pushed.  Also used to copy the rest of a DCC, after IP
+          address and port has been handled */
+        lBAD_CTCP:
+                for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
+                        newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
+                        if(sptr[i] == '\001') {
+                                goto lNORMAL_TEXT;
+                        }
+                }
+                goto lPACKET_DONE;
+                /* Normal text */
+        lNORMAL_TEXT:
+                for(; i<dlen && iCopy<sizeof(newpacket); i++,iCopy++) {
+                        newpacket[iCopy] = sptr[i]; /* Copy CTCP unchanged */
+                        if(sptr[i] == '\001') {
+                                goto lCTCP_START;
+                        }
+                }
+                /* Handle the end of a packet */
+        lPACKET_DONE:
+                iCopy = iCopy > maxsize-copyat ? maxsize-copyat : iCopy;
+                memcpy(sptr+copyat, newpacket, iCopy);
+
+/* Save information regarding modified seq and ack numbers */
+        {
+            int delta;
+
+            SetAckModified(link);
+            delta = GetDeltaSeqOut(pip, link);
+            AddSeq(pip, link, delta+copyat+iCopy-dlen);
+        }
+
+                 /* Revise IP header */
+        {
+                         u_short new_len;
+                         
+                         new_len = htons(hlen + iCopy + copyat);
+                         DifferentialChecksum(&pip->ip_sum,
+                                                                                 &new_len,
+                                                                                 &pip->ip_len,
+                                                                                 1);
+                         pip->ip_len = new_len;
+        }
+
+                 /* Compute TCP checksum for revised packet */
+        tc->th_sum = 0;
+        tc->th_sum = TcpChecksum(pip);
+                 return;
+        }
+}
+
+/* Notes:
+       [Note 1]
+       The initial search will most often fail; it could be replaced with a 32-bit specific search.
+       Such a search would be done for 32-bit unsigned value V:
+       V ^= 0x01010101;                                  (Search is for null bytes)
+       if( ((V-0x01010101)^V) & 0x80808080 ) {
+     (found a null bytes which was a 01 byte)
+       }
+   To assert that the processor is 32-bits, do
+   extern int ircdccar[32];        (32 bits)
+   extern int ircdccar[CHAR_BIT*sizeof(unsigned int)];
+   which will generate a type-error on all but 32-bit machines.
+
+       [Note 2] This routine really ought to be replaced with one that
+       creates a transparent proxy on the aliasing host, to allow arbitary
+       changes in the TCP stream.  This should not be too difficult given
+       this base;  I (ee) will try to do this some time later.
+       */
diff --git a/alias/alias_local.h b/alias/alias_local.h
new file mode 100644 (file)
index 0000000..23b04a8
--- /dev/null
@@ -0,0 +1,170 @@
+/* -*- mode: c; tab-width: 3; c-basic-offset: 3; -*-
+    Alias_local.h contains the function prototypes for alias.c,
+    alias_db.c, alias_util.c and alias_ftp.c, alias_irc.c (as well
+    as any future add-ons).  It also includes macros, globals and
+    struct definitions shared by more than one alias*.c file.
+
+    This include file is intended to be used only within the aliasing
+    software.  Outside world interfaces are defined in alias.h
+
+    This software is placed into the public domain with no restrictions
+    on its distribution.
+
+    Initial version:  August, 1996  (cjm)    
+    
+     <updated several times by original author and Eivind Eiklund>
+*/
+#ifndef ALIAS_LOCAL_H
+#define ALIAS_LOCAL_H
+
+
+/*
+    Macros
+ */
+
+/*
+   The following macro is used to update an
+   internet checksum.  "delta" is a 32-bit
+   accumulation of all the changes to the
+   checksum (adding in new 16-bit words and
+   subtracting out old words), and "cksum"
+   is the checksum value to be updated.
+*/
+#define ADJUST_CHECKSUM(acc, cksum) { \
+    acc += cksum; \
+    if (acc < 0) \
+    { \
+        acc = -acc; \
+        acc = (acc >> 16) + (acc & 0xffff); \
+        acc += acc >> 16; \
+        cksum = (u_short) ~acc; \
+    } \
+    else \
+    { \
+        acc = (acc >> 16) + (acc & 0xffff); \
+        acc += acc >> 16; \
+        cksum = (u_short) acc; \
+    } \
+}
+
+
+/*
+    Globals
+*/
+
+extern int packetAliasMode;
+
+
+/*
+    Structs
+*/
+
+struct alias_link;    /* Incomplete structure */
+
+
+/*
+    Prototypes
+*/
+
+/* General utilities */
+u_short IpChecksum(struct ip *);
+u_short TcpChecksum(struct ip *);
+void DifferentialChecksum(u_short *, u_short *, u_short *, int);
+
+/* Internal data access */
+struct alias_link *
+FindIcmpIn(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+FindIcmpOut(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+FindFragmentIn1(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+FindFragmentIn2(struct in_addr, struct in_addr, u_short);
+
+struct alias_link *
+AddFragmentPtrLink(struct in_addr, u_short);
+
+struct alias_link *
+FindFragmentPtr(struct in_addr, u_short);
+
+struct alias_link *
+FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char);
+
+struct alias_link *
+FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char);
+
+struct in_addr
+FindOriginalAddress(struct in_addr);
+
+struct in_addr
+FindAliasAddress(struct in_addr);
+
+/* External data access/modification */
+void GetFragmentAddr(struct alias_link *, struct in_addr *);
+void SetFragmentAddr(struct alias_link *, struct in_addr);
+void GetFragmentPtr(struct alias_link *, char **);
+void SetFragmentPtr(struct alias_link *, char *);
+void SetStateIn(struct alias_link *, int);
+void SetStateOut(struct alias_link *, int);
+int GetStateIn(struct alias_link *);
+int GetStateOut(struct alias_link *);
+struct in_addr GetOriginalAddress(struct alias_link *);
+struct in_addr GetDestAddress(struct alias_link *);
+struct in_addr GetAliasAddress(struct alias_link *);
+struct in_addr GetDefaultAliasAddress(void);
+void SetDefaultAliasAddress(struct in_addr);
+u_short GetOriginalPort(struct alias_link *);
+u_short GetAliasPort(struct alias_link *);
+struct in_addr GetProxyAddress(struct alias_link *);
+void SetProxyAddress(struct alias_link *, struct in_addr);
+u_short GetProxyPort(struct alias_link *);
+void SetProxyPort(struct alias_link *, u_short);
+void SetAckModified(struct alias_link *);
+int GetAckModified(struct alias_link *);
+int GetDeltaAckIn(struct ip *, struct alias_link *);
+int GetDeltaSeqOut(struct ip *, struct alias_link *);
+void AddSeq(struct ip *, struct alias_link *, int);
+void SetExpire(struct alias_link *, int);
+void ClearCheckNewLink(void);
+#ifndef NO_FW_PUNCH
+void PunchFWHole(struct alias_link *);
+#endif
+
+
+/* Housekeeping function */
+void HouseKeeping(void);
+
+/* Tcp specfic routines */
+/*lint -save -library Suppress flexelint warnings */
+
+/* FTP routines */
+void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
+
+/* IRC routines */
+void AliasHandleIrcOut(struct ip *, struct alias_link *, int);
+
+/* NetBIOS routines */
+int AliasHandleUdpNbt(struct ip *, struct alias_link *, struct in_addr *, u_short);
+int AliasHandleUdpNbtNS(struct ip *, struct alias_link *, struct in_addr *, u_short *, struct in_addr *, u_short *);
+
+/* CUSeeMe routines */
+void AliasHandleCUSeeMeOut(struct ip *, struct alias_link *);
+void AliasHandleCUSeeMeIn(struct ip *, struct in_addr);
+
+/* Transparent proxy routines */
+int ProxyCheck(struct ip *, struct in_addr *, u_short *);
+void ProxyModify(struct alias_link *, struct ip *, int, int);
+
+
+enum alias_tcp_state {
+    ALIAS_TCP_STATE_NOT_CONNECTED,
+    ALIAS_TCP_STATE_CONNECTED,
+    ALIAS_TCP_STATE_DISCONNECTED
+};
+
+int GetPptpAlias (struct in_addr*);
+/*lint -restore */
+#endif /* defined(ALIAS_LOCAL_H) */
diff --git a/alias/alias_nbt.c b/alias/alias_nbt.c
new file mode 100644 (file)
index 0000000..b629b8e
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ * Written by Atsushi Murai <amurai@spec.co.jp>
+ *
+ * Copyright (C) 1998, System Planning and Engineering Co. All rights reserverd.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the System Planning and Engineering Co.  The name of the
+ * SPEC may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: alias_nbt.c,v 1.1.1.1 2000/01/11 01:48:42 wsanchez Exp $
+ *
+ *  TODO:
+ *       oClean up. 
+ *       oConsidering for word alignment for other platform.
+ */
+/*
+    alias_nbt.c performs special processing for NetBios over TCP/IP
+    sessions by UDP.
+
+    Initial version:  May, 1998  (Atsushi Murai <amurai@spec.co.jp>)
+
+    See HISTORY file for record of revisions.
+*/
+
+/* Includes */
+#include <ctype.h>
+#include <stdio.h> 
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+
+#include "alias_local.h"
+
+#define ADJUST_CHECKSUM(acc, cksum) { \
+    acc += cksum; \
+    if (acc < 0) \
+    { \
+        acc = -acc; \
+        acc = (acc >> 16) + (acc & 0xffff); \
+        acc += acc >> 16; \
+        cksum = (u_short) ~acc; \
+    } \
+    else \
+    { \
+        acc = (acc >> 16) + (acc & 0xffff); \
+        acc += acc >> 16; \
+        cksum = (u_short) acc; \
+    } \
+}
+
+typedef struct {
+       struct in_addr          oldaddr;
+       u_short                         oldport;
+       struct in_addr          newaddr;
+       u_short                         newport;
+       u_short                         *uh_sum;
+} NBTArguments;
+
+typedef struct {
+       unsigned char   type;
+       unsigned char   flags;
+       u_short                 id;
+       struct in_addr  source_ip;
+       u_short                 source_port;
+       u_short                 len;
+       u_short                 offset;
+} NbtDataHeader;
+
+#define OpQuery                0
+#define OpUnknown      4
+#define OpRegist       5
+#define OpRelease      6
+#define OpWACK         7
+#define OpRefresh      8
+typedef struct {
+       u_short                 nametrid;
+       u_short                 dir:1, opcode:4, nmflags:7, rcode:4;
+       u_short                 qdcount;
+       u_short                 ancount;
+       u_short                 nscount;
+       u_short                 arcount;
+} NbtNSHeader;
+
+#define FMT_ERR                0x1
+#define SRV_ERR                0x2
+#define IMP_ERR                0x4
+#define RFS_ERR                0x5
+#define ACT_ERR                0x6
+#define CFT_ERR                0x7
+
+
+#ifdef DEBUG
+static void PrintRcode( u_char rcode )  {
+
+       switch (rcode) {
+               case FMT_ERR:
+                       printf("\nFormat Error.");
+               case SRV_ERR:
+                       printf("\nSever failure.");
+               case IMP_ERR:
+                       printf("\nUnsupported request error.\n");
+               case RFS_ERR:
+                       printf("\nRefused error.\n");
+               case ACT_ERR:
+                       printf("\nActive error.\n");
+               case CFT_ERR:
+                       printf("\nName in conflict error.\n");
+               default:
+                       printf("\n???=%0x\n", rcode );
+
+       }       
+}
+#endif
+
+
+/* Handling Name field */
+static u_char *AliasHandleName ( u_char *p, char *pmax ) {
+
+       u_char *s;
+       u_char c;
+       int             compress;
+
+       /* Following length field */
+
+       if (p == NULL || (char *)p >= pmax)
+               return(NULL);
+
+       if (*p & 0xc0 ) {
+               p = p + 2;
+               if ((char *)p > pmax)
+                       return(NULL);
+               return ((u_char *)p);
+       }
+       while ( ( *p & 0x3f) != 0x00 ) {
+               s = p + 1;
+               if ( *p == 0x20 )
+                       compress = 1;
+               else
+                       compress = 0;
+               
+               /* Get next length field */
+               p = (u_char *)(p + (*p & 0x3f) + 1);
+               if ((char *)p > pmax) {
+                       p = NULL;
+                       break;
+               }
+#ifdef DEBUG
+               printf(":");
+#endif
+               while (s < p) {
+                       if ( compress == 1 ) {
+                               c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
+#ifdef DEBUG
+                               if (isprint( c ) )
+                                       printf("%c", c );
+                               else
+                                       printf("<0x%02x>", c );
+#endif
+                               s +=2;
+                       } else {
+#ifdef DEBUG
+                               printf("%c", *s);
+#endif
+                               s++;
+                       }
+               }
+#ifdef DEBUG
+               printf(":");
+#endif
+               fflush(stdout);
+    }
+
+       /* Set up to out of Name field */
+       if (p == NULL || (char *)p >= pmax)
+           p = NULL;
+       else
+           p++;
+       return ((u_char *)p);
+}
+
+/* 
+ * NetBios Datagram Handler (IP/UDP)
+ */
+#define DGM_DIRECT_UNIQ                0x10
+#define DGM_DIRECT_GROUP       0x11
+#define DGM_BROADCAST          0x12
+#define DGM_ERROR                      0x13
+#define DGM_QUERY                      0x14
+#define DGM_POSITIVE_RES       0x15
+#define DGM_NEGATIVE_RES       0x16
+
+int AliasHandleUdpNbt(
+       struct ip                       *pip,    /* IP packet to examine/patch */
+       struct alias_link       *link,
+       struct in_addr          *alias_address,
+    u_short            alias_port
+) {
+    struct udphdr *    uh;
+    NbtDataHeader      *ndh;
+    u_char             *p = NULL;
+    char               *pmax;
+        
+    /* Calculate data length of UDP packet */
+    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+    pmax = (char *)uh + ntohs( uh->uh_ulen );
+
+       ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
+    if ((char *)(ndh + 1) > pmax)
+           return(-1);
+#ifdef DEBUG
+       printf("\nType=%02x,", ndh->type );
+#endif
+       switch ( ndh->type ) {
+               case DGM_DIRECT_UNIQ:
+               case DGM_DIRECT_GROUP:
+               case DGM_BROADCAST:
+                       p = (u_char *)ndh + 14;
+                   p = AliasHandleName ( p, pmax ); /* Source Name */
+                   p = AliasHandleName ( p, pmax ); /* Destination Name */
+                       break;
+               case DGM_ERROR:
+                       p = (u_char *)ndh + 11;
+                       break;
+               case DGM_QUERY:
+               case DGM_POSITIVE_RES:
+               case DGM_NEGATIVE_RES:
+                       p = (u_char *)ndh + 10;
+                   p = AliasHandleName ( p, pmax ); /* Destination Name */
+                       break;
+       }
+    if (p == NULL || (char *)p > pmax)
+           p = NULL;
+#ifdef DEBUG
+       printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
+#endif
+       /* Doing a IP address and Port number Translation */
+       if ( uh->uh_sum != 0 ) {
+               int                             acc;
+               u_short                 *sptr;
+               acc  = ndh->source_port;
+               acc -= alias_port;
+               sptr = (u_short *) &(ndh->source_ip);
+               acc += *sptr++;
+               acc += *sptr;
+               sptr = (u_short *) alias_address;
+               acc -= *sptr++;
+               acc -= *sptr;
+               ADJUST_CHECKSUM(acc, uh->uh_sum)
+       }
+    ndh->source_ip = *alias_address;
+    ndh->source_port = alias_port;
+#ifdef DEBUG
+       printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
+       fflush(stdout);
+#endif
+    return((p == NULL) ? -1 : 0);
+}
+/* Question Section */
+#define QS_TYPE_NB             0x0020
+#define QS_TYPE_NBSTAT 0x0021
+#define QS_CLAS_IN             0x0001
+typedef struct {
+       u_short type;   /* The type of Request */
+       u_short class;  /* The class of Request */
+} NBTNsQuestion;
+
+static u_char *
+AliasHandleQuestion(
+    u_short count,
+                                                       NBTNsQuestion *q,
+    char *pmax,
+                                                       NBTArguments  *nbtarg)
+{
+
+       while ( count != 0 ) {
+               /* Name Filed */
+               q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
+
+               if (q == NULL || (char *)(q + 1) > pmax) {
+                       q = NULL;
+                       break;
+               }
+
+               /* Type and Class filed */
+               switch ( ntohs(q->type) ) {
+                       case QS_TYPE_NB:
+                       case QS_TYPE_NBSTAT:
+                               q= q+1;
+                       break;
+                       default:
+#ifdef DEBUG
+                               printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
+#endif
+                       break;
+               }
+               count--;
+       }
+
+       /* Set up to out of Question Section */
+       return ((u_char *)q);
+}
+
+/* Resource Record */
+#define RR_TYPE_A              0x0001
+#define RR_TYPE_NS             0x0002
+#define RR_TYPE_NULL   0x000a
+#define RR_TYPE_NB             0x0020
+#define RR_TYPE_NBSTAT 0x0021
+#define RR_CLAS_IN             0x0001
+#define SizeOfNsResource       8
+typedef struct {
+       u_short type;
+       u_short class;
+       unsigned int ttl;
+       u_short rdlen;
+} NBTNsResource;
+
+#define SizeOfNsRNB                    6
+typedef struct {
+       u_short g:1, ont:2, resv:13;
+       struct  in_addr addr;
+} NBTNsRNB;
+
+static u_char *
+AliasHandleResourceNB( 
+    NBTNsResource *q,
+    char *pmax, 
+                                                          NBTArguments  *nbtarg)
+{
+       NBTNsRNB        *nb;
+       u_short bcount;
+
+       if (q == NULL || (char *)(q + 1) > pmax)
+               return(NULL);
+       /* Check out a length */
+       bcount = ntohs(q->rdlen);
+
+       /* Forward to Resource NB position */
+       nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
+
+       /* Processing all in_addr array */
+#ifdef DEBUG
+       printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
+            printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
+#endif
+       while ( nb != NULL && bcount != 0 )  {
+               if ((char *)(nb + 1) > pmax) {
+                       nb = NULL;
+                       break;
+               }
+#ifdef DEBUG
+               printf("<%s>", inet_ntoa(nb->addr) );
+#endif
+               if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
+                       if ( *nbtarg->uh_sum != 0 ) {
+               int acc;
+               u_short *sptr;
+
+               sptr = (u_short *) &(nb->addr);
+               acc = *sptr++;
+               acc += *sptr;
+               sptr = (u_short *) &(nbtarg->newaddr);
+               acc -= *sptr++;
+               acc -= *sptr;
+               ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
+                       }
+
+                       nb->addr = nbtarg->newaddr;
+#ifdef DEBUG
+                       printf("O");
+#endif
+               }
+#ifdef DEBUG
+                else {
+                       printf(".");
+               }
+#endif
+               nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
+               bcount -= SizeOfNsRNB;
+       }
+       if (nb == NULL || (char *)(nb + 1) > pmax) {
+               nb = NULL;
+       }
+
+       return ((u_char *)nb);
+}
+
+#define SizeOfResourceA                6
+typedef struct {
+       struct  in_addr addr;
+} NBTNsResourceA;
+
+static u_char *
+AliasHandleResourceA( 
+    NBTNsResource *q,
+    char *pmax,
+                                                         NBTArguments  *nbtarg)
+{
+       NBTNsResourceA  *a;
+       u_short bcount;
+
+       if (q == NULL || (char *)(q + 1) > pmax)
+               return(NULL);
+
+       /* Forward to Resource A position */
+       a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
+
+       /* Check out of length */
+       bcount = ntohs(q->rdlen);
+
+       /* Processing all in_addr array */
+#ifdef DEBUG
+       printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
+        printf("->%s]",inet_ntoa(nbtarg->newaddr ));
+#endif
+       while ( bcount != 0 )  {
+               if (a == NULL || (char *)(a + 1) > pmax)
+                       return(NULL);
+#ifdef DEBUG
+               printf("..%s", inet_ntoa(a->addr) );
+#endif
+               if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
+                       if ( *nbtarg->uh_sum != 0 ) {
+               int acc;
+               u_short *sptr;
+
+               sptr = (u_short *) &(a->addr);           /* Old */
+               acc = *sptr++;
+               acc += *sptr;
+               sptr = (u_short *) &nbtarg->newaddr; /* New */
+               acc -= *sptr++;
+               acc -= *sptr;
+               ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
+                       }
+
+                       a->addr = nbtarg->newaddr;
+               }
+               a++;    /*XXXX*/
+               bcount -= SizeOfResourceA;
+       }
+       if (a == NULL || (char *)(a + 1) > pmax)
+               a =  NULL;
+       return ((u_char *)a);
+}
+
+typedef struct {
+       u_short opcode:4, flags:8, resv:4;
+} NBTNsResourceNULL;
+
+static u_char *
+AliasHandleResourceNULL( 
+    NBTNsResource *q, 
+    char *pmax,
+                                                            NBTArguments  *nbtarg)
+{
+       NBTNsResourceNULL       *n;
+       u_short bcount;
+
+       if (q == NULL || (char *)(q + 1) > pmax)
+               return(NULL);
+
+       /* Forward to Resource NULL position */
+       n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
+
+       /* Check out of length */
+       bcount = ntohs(q->rdlen);
+
+       /* Processing all in_addr array */
+       while ( bcount != 0 )  {
+               if ((char *)(n + 1) > pmax) {
+                       n = NULL;
+                       break;
+               }
+               n++;
+               bcount -= sizeof(NBTNsResourceNULL);
+       }
+       if ((char *)(n + 1) > pmax)
+               n = NULL;
+
+       return ((u_char *)n);
+}
+
+static u_char *
+AliasHandleResourceNS( 
+    NBTNsResource *q,
+    char *pmax,
+                                                            NBTArguments  *nbtarg)
+{
+       NBTNsResourceNULL       *n;
+       u_short bcount;
+
+       if (q == NULL || (char *)(q + 1) > pmax)
+               return(NULL);
+
+       /* Forward to Resource NULL position */
+       n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
+
+       /* Check out of length */
+       bcount = ntohs(q->rdlen);
+
+       /* Resource Record Name Filed */
+       q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
+
+       if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
+               return(NULL);
+       else
+       return ((u_char *)n + bcount);
+}
+
+typedef struct {
+       u_short numnames;
+} NBTNsResourceNBSTAT;
+
+static u_char *
+AliasHandleResourceNBSTAT(
+    NBTNsResource *q,
+    char *pmax,
+                                                              NBTArguments  *nbtarg)
+{
+       NBTNsResourceNBSTAT     *n;
+       u_short bcount;
+
+       if (q == NULL || (char *)(q + 1) > pmax)
+               return(NULL);
+
+       /* Forward to Resource NBSTAT position */
+       n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
+
+       /* Check out of length */
+       bcount = ntohs(q->rdlen);
+
+       if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
+               return(NULL);
+       else
+       return ((u_char *)n + bcount);
+}
+
+static u_char *
+AliasHandleResource(
+    u_short count, 
+                                                       NBTNsResource *q,
+    char *pmax,
+    NBTArguments  
+    *nbtarg)
+{
+       while ( count != 0 ) {
+               /* Resource Record Name Filed */
+               q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
+
+               if (q == NULL || (char *)(q + 1) > pmax)
+                       break;
+#ifdef DEBUG
+               printf("type=%02x, count=%d\n", ntohs(q->type), count );
+#endif
+
+               /* Type and Class filed */
+               switch ( ntohs(q->type) ) {
+                       case RR_TYPE_NB:
+                               q = (NBTNsResource *)AliasHandleResourceNB( 
+                                   q,
+                                   pmax,
+                                   nbtarg 
+                               );
+                               break;
+                       case RR_TYPE_A: 
+                               q = (NBTNsResource *)AliasHandleResourceA( 
+                                   q, 
+                                   pmax, 
+                                   nbtarg
+                               );
+                               break;
+                       case RR_TYPE_NS:
+                               q = (NBTNsResource *)AliasHandleResourceNS( 
+                                   q,
+                                   pmax, 
+                                   nbtarg 
+                               );
+                               break;
+                       case RR_TYPE_NULL:
+                               q = (NBTNsResource *)AliasHandleResourceNULL( 
+                                   q, 
+                                   pmax, 
+                                   nbtarg 
+                               );
+                               break;
+                       case RR_TYPE_NBSTAT:
+                               q = (NBTNsResource *)AliasHandleResourceNBSTAT(
+                                   q,
+                                   pmax, 
+                                   nbtarg
+                               );
+                               break;
+                       default: 
+#ifdef DEBUG
+                               printf(
+                                   "\nUnknown Type of Resource %0x\n", 
+                                   ntohs(q->type) 
+                               );
+#endif
+                               break;
+               }
+               count--;
+       }
+       fflush(stdout);
+       return ((u_char *)q);
+}
+
+int AliasHandleUdpNbtNS(
+       struct ip                       *pip,    /* IP packet to examine/patch */
+       struct alias_link       *link,
+       struct in_addr          *alias_address,
+       u_short                         *alias_port,
+       struct in_addr          *original_address,
+       u_short                         *original_port )
+{
+    struct udphdr *    uh;
+       NbtNSHeader       * nsh;
+       u_char            * p;
+       char            *pmax;
+       NBTArguments    nbtarg;
+
+       /* Set up Common Parameter */   
+       nbtarg.oldaddr  =       *alias_address;
+       nbtarg.oldport  =       *alias_port;
+       nbtarg.newaddr  =       *original_address;
+       nbtarg.newport  =       *original_port;
+
+    /* Calculate data length of UDP packet */
+    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+       nbtarg.uh_sum   =       &(uh->uh_sum);
+       nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
+       p = (u_char *)(nsh + 1);
+    pmax = (char *)uh + ntohs( uh->uh_ulen );
+
+    if ((char *)(nsh + 1) > pmax)
+       return(-1);
+
+#ifdef DEBUG
+    printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
+          ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 
+               nsh->dir ? "Response": "Request",
+               nsh->nametrid,
+               nsh->opcode,
+               nsh->nmflags,
+               nsh->rcode,
+               ntohs(nsh->qdcount),
+               ntohs(nsh->ancount),
+               ntohs(nsh->nscount),
+               ntohs(nsh->arcount),
+       (u_char *)p -(u_char *)nsh
+    );
+#endif
+
+       /* Question Entries */
+       if (ntohs(nsh->qdcount) !=0 ) {
+       p = AliasHandleQuestion(
+           ntohs(nsh->qdcount),
+           (NBTNsQuestion *)p,
+           pmax, 
+           &nbtarg 
+       );
+       }
+
+       /* Answer Resource Records */
+       if (ntohs(nsh->ancount) !=0 ) {
+       p = AliasHandleResource(
+           ntohs(nsh->ancount),
+           (NBTNsResource *)p,
+           pmax, 
+           &nbtarg 
+       );
+       }
+
+       /* Authority Resource Recodrs */
+       if (ntohs(nsh->nscount) !=0 ) {
+       p = AliasHandleResource(
+           ntohs(nsh->nscount), 
+           (NBTNsResource *)p,
+           pmax, 
+           &nbtarg 
+       );
+       }
+
+       /* Additional Resource Recodrs */
+       if (ntohs(nsh->arcount) !=0 ) {
+       p = AliasHandleResource(
+           ntohs(nsh->arcount),
+           (NBTNsResource *)p,
+           pmax, 
+           &nbtarg 
+       );
+       }
+
+#ifdef DEBUG
+               PrintRcode(nsh->rcode);
+#endif
+    return ((p == NULL) ? -1 : 0);
+}
diff --git a/alias/alias_proxy.c b/alias/alias_proxy.c
new file mode 100644 (file)
index 0000000..60437bf
--- /dev/null
@@ -0,0 +1,805 @@
+/* file: alias_proxy.c
+
+    This file encapsulates special operations related to transparent
+    proxy redirection.  This is where packets with a particular destination,
+    usually tcp port 80, are redirected to a proxy server.
+
+    When packets are proxied, the destination address and port are
+    modified.  In certain cases, it is necessary to somehow encode
+    the original address/port info into the packet.  Two methods are
+    presently supported: addition of a [DEST addr port] string at the
+    beginning a of tcp stream, or inclusion of an optional field
+    in the IP header.
+    
+    There is one public API function:
+
+        PacketAliasProxyRule()    -- Adds and deletes proxy
+                                     rules.
+
+    Rules are stored in a linear linked list, so lookup efficiency
+    won't be too good for large lists.
+
+
+    Initial development: April, 1998 (cjm)
+*/
+
+
+/* System includes */
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/* BSD IPV4 includes */
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <arpa/inet.h>
+
+#include "alias_local.h"  /* Functions used by alias*.c */
+#include "alias.h"        /* Public API functions for libalias */
+
+
+
+/*
+    Data structures
+ */
+
+/*
+ * A linked list of arbitrary length, based on struct proxy_entry is
+ * used to store proxy rules.
+ */
+struct proxy_entry
+{
+#define PROXY_TYPE_ENCODE_NONE      1
+#define PROXY_TYPE_ENCODE_TCPSTREAM 2
+#define PROXY_TYPE_ENCODE_IPHDR     3
+    int rule_index;
+    int proxy_type;
+    u_char proto;
+    u_short proxy_port;
+    u_short server_port;
+
+    struct in_addr server_addr;
+
+    struct in_addr src_addr;
+    struct in_addr src_mask;
+
+    struct in_addr dst_addr;
+    struct in_addr dst_mask;
+
+    struct proxy_entry *next;
+    struct proxy_entry *last;
+};
+
+
+
+/*
+    File scope variables
+*/
+
+static struct proxy_entry *proxyList;
+
+
+
+/* Local (static) functions:
+
+    IpMask()                 -- Utility function for creating IP
+                                masks from integer (1-32) specification.
+    IpAddr()                 -- Utility function for converting string
+                                to IP address
+    IpPort()                 -- Utility function for converting string
+                                to port number
+    RuleAdd()                -- Adds an element to the rule list.
+    RuleDelete()             -- Removes an element from the rule list.
+    RuleNumberDelete()       -- Removes all elements from the rule list
+                                having a certain rule number.
+    ProxyEncodeTcpStream()   -- Adds [DEST x.x.x.x xxxx] to the beginning
+                                of a TCP stream.
+    ProxyEncodeIpHeader()    -- Adds an IP option indicating the true
+                                destination of a proxied IP packet
+*/
+
+static int IpMask(int, struct in_addr *);
+static int IpAddr(char *, struct in_addr *);
+static int IpPort(char *, int, int *);
+static void RuleAdd(struct proxy_entry *);
+static void RuleDelete(struct proxy_entry *);
+static int RuleNumberDelete(int);
+static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
+static void ProxyEncodeIpHeader(struct ip *, int);
+
+static int
+IpMask(int nbits, struct in_addr *mask)
+{
+    int i;
+    u_int imask;
+
+    if (nbits < 0 || nbits > 32)
+        return -1;
+
+    imask = 0;
+    for (i=0; i<nbits; i++)
+        imask = (imask >> 1) + 0x80000000;
+    mask->s_addr = htonl(imask);
+
+    return 0;
+}
+
+static int
+IpAddr(char *s, struct in_addr *addr)
+{
+    if (inet_aton(s, addr) == 0)
+        return -1;
+    else
+        return 0;
+}
+
+static int
+IpPort(char *s, int proto, int *port)
+{
+    int n;
+
+    n = sscanf(s, "%d", port);
+    if (n != 1)
+    {
+        struct servent *se;
+
+        if (proto == IPPROTO_TCP)
+            se = getservbyname(s, "tcp");
+        else if (proto == IPPROTO_UDP)
+            se = getservbyname(s, "udp");
+        else
+            return -1;
+
+        if (se == NULL)
+                return -1;
+
+        *port = (u_int) ntohs(se->s_port);
+    }
+
+    return 0;
+}
+
+void
+RuleAdd(struct proxy_entry *entry)
+{
+    int rule_index;
+    struct proxy_entry *ptr;
+    struct proxy_entry *ptr_last;
+
+    if (proxyList == NULL)
+    {
+        proxyList = entry;
+        entry->last = NULL;
+        entry->next = NULL;
+        return;
+    }
+
+    rule_index = entry->rule_index;
+    ptr = proxyList;
+    ptr_last = NULL;
+    while (ptr != NULL)
+    {
+        if (ptr->rule_index >= rule_index)
+        {
+            if (ptr_last == NULL)
+            {
+                entry->next = proxyList;
+                entry->last = NULL;
+                proxyList->last = entry;
+                proxyList = entry;
+                return;
+            }
+
+            ptr_last->next = entry;
+            ptr->last = entry;
+            entry->last = ptr->last;
+            entry->next = ptr;
+            return;
+        }
+        ptr_last = ptr;
+        ptr = ptr->next;
+    }
+
+    ptr_last->next = entry;
+    entry->last = ptr_last;
+    entry->next = NULL;
+}
+
+static void
+RuleDelete(struct proxy_entry *entry)
+{
+    if (entry->last != NULL)
+        entry->last->next = entry->next;
+    else
+        proxyList = entry->next;
+
+    if (entry->next != NULL)
+        entry->next->last = entry->last;
+
+    free(entry);
+}
+
+static int
+RuleNumberDelete(int rule_index)
+{
+    int err;
+    struct proxy_entry *ptr;
+
+    err = -1;
+    ptr = proxyList;
+    while (ptr != NULL)
+    {
+        struct proxy_entry *ptr_next;
+
+        ptr_next = ptr->next;
+        if (ptr->rule_index == rule_index)
+        {
+            err = 0;
+            RuleDelete(ptr);
+        }
+
+        ptr = ptr_next;
+    }
+
+    return err;
+}
+
+static void
+ProxyEncodeTcpStream(struct alias_link *link,
+                     struct ip *pip,
+                     int maxpacketsize)
+{
+    int slen;
+    char buffer[40];
+    struct tcphdr *tc;
+
+/* Compute pointer to tcp header */
+    tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+/* Don't modify if once already modified */
+
+    if (GetAckModified (link))
+       return;
+
+/* Translate destination address and port to string form */
+    snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
+        inet_ntoa(GetProxyAddress (link)), (u_int) ntohs(GetProxyPort (link)));
+    
+/* Pad string out to a multiple of two in length */
+    slen = strlen(buffer);
+    switch (slen % 2)
+    {
+    case 0:
+        strcat(buffer, " \n");
+       slen += 2;
+        break;
+    case 1:
+        strcat(buffer, "\n");
+       slen += 1;
+    }
+
+/* Check for packet overflow */
+    if ((ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
+        return;
+
+/* Shift existing TCP data and insert destination string */
+    {
+        int dlen;
+        int hlen;
+        u_char *p;
+
+        hlen = (pip->ip_hl + tc->th_off) << 2;
+        dlen = ntohs (pip->ip_len) - hlen;
+
+/* Modify first packet that has data in it */
+
+       if (dlen == 0)
+               return;
+
+        p = (char *) pip;
+        p += hlen;
+
+        memmove(p + slen, p, dlen);
+        memcpy(p, buffer, slen);
+    }
+
+/* Save information about modfied sequence number */
+    {
+        int delta;
+
+        SetAckModified(link);
+        delta = GetDeltaSeqOut(pip, link);
+        AddSeq(pip, link, delta+slen);
+    }
+
+/* Update IP header packet length and checksum */
+    {
+        int accumulate;
+
+        accumulate  = pip->ip_len;
+        pip->ip_len = htons(ntohs(pip->ip_len) + slen);
+        accumulate -= pip->ip_len;
+
+        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
+    }
+
+/* Update TCP checksum, Use TcpChecksum since so many things have
+   already changed. */
+
+    tc->th_sum = 0;
+    tc->th_sum = TcpChecksum (pip);
+}
+
+static void
+ProxyEncodeIpHeader(struct ip *pip,
+                    int maxpacketsize)
+{
+#define OPTION_LEN_BYTES  8
+#define OPTION_LEN_INT16  4
+#define OPTION_LEN_INT32  2
+    u_char option[OPTION_LEN_BYTES];
+
+#ifdef DEBUG
+    fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip));
+    fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip));
+#endif
+
+/* Check to see that there is room to add an IP option */
+    if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
+        return;
+
+/* Build option and copy into packet */
+    {
+        u_char *ptr;
+        struct tcphdr *tc;
+
+        ptr = (u_char *) pip;
+        ptr += 20;
+        memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
+
+        option[0] = 0x64; /* class: 3 (reserved), option 4 */
+        option[1] = OPTION_LEN_BYTES;
+
+        memcpy(&option[2], (u_char *) &pip->ip_dst, 4);
+
+        tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
+        memcpy(&option[6], (u_char *) &tc->th_sport, 2);
+
+        memcpy(ptr, option, 8);
+    }
+
+/* Update checksum, header length and packet length */
+    {
+        int i;
+        int accumulate;
+        u_short *sptr;
+
+        sptr = (u_short *) option;
+        accumulate = 0;
+        for (i=0; i<OPTION_LEN_INT16; i++)
+            accumulate -= *(sptr++);
+
+        sptr = (u_short *) pip;
+        accumulate += *sptr;
+        pip->ip_hl += OPTION_LEN_INT32;
+        accumulate -= *sptr;
+
+        accumulate += pip->ip_len;
+        pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
+        accumulate -= pip->ip_len;
+
+        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
+    }
+#undef OPTION_LEN_BYTES
+#undef OPTION_LEN_INT16
+#undef OPTION_LEN_INT32
+#ifdef DEBUG
+    fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip));
+    fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip));
+#endif
+}
+
+
+/* Functions by other packet alias source files
+
+    ProxyCheck()         -- Checks whether an outgoing packet should
+                            be proxied.
+    ProxyModify()        -- Encodes the original destination address/port
+                            for a packet which is to be redirected to
+                            a proxy server.
+*/
+
+int
+ProxyCheck(struct ip *pip,
+           struct in_addr *proxy_server_addr,
+           u_short *proxy_server_port)
+{
+    u_short dst_port;
+    struct in_addr src_addr;
+    struct in_addr dst_addr;
+    struct proxy_entry *ptr;
+
+    src_addr = pip->ip_src;
+    dst_addr = pip->ip_dst;
+    dst_port = ((struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)))
+        ->th_dport;
+
+    ptr = proxyList;
+    while (ptr != NULL)
+    {
+        u_short proxy_port;
+
+        proxy_port = ptr->proxy_port;
+        if ((dst_port == proxy_port || proxy_port == 0)
+         && pip->ip_p == ptr->proto
+         && src_addr.s_addr != ptr->server_addr.s_addr)
+        {
+            struct in_addr src_addr_masked;
+            struct in_addr dst_addr_masked;
+
+            src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
+            dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
+
+            if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
+             && (dst_addr_masked.s_addr == ptr->dst_addr.s_addr))
+            {
+                if ((*proxy_server_port = ptr->server_port) == 0)
+                    *proxy_server_port = dst_port;
+                *proxy_server_addr = ptr->server_addr;
+                return ptr->proxy_type;
+            }
+        }
+        ptr = ptr->next;
+    }
+
+    return 0;
+}
+
+void
+ProxyModify(struct alias_link *link,
+            struct ip *pip,
+            int maxpacketsize,
+            int proxy_type)
+{
+    switch (proxy_type)
+    {
+    case PROXY_TYPE_ENCODE_IPHDR:
+        ProxyEncodeIpHeader(pip, maxpacketsize);
+        break;
+
+    case PROXY_TYPE_ENCODE_TCPSTREAM:
+        ProxyEncodeTcpStream(link, pip, maxpacketsize);
+        break;
+    }
+}
+
+
+/*
+    Public API functions
+*/
+
+int
+PacketAliasProxyRule(const char *cmd)
+{
+/*
+ * This function takes command strings of the form:
+ *
+ *   server <addr>[:<port>]
+ *   [port <port>]
+ *   [rule n]
+ *   [proto tcp|udp]
+ *   [src <addr>[/n]]
+ *   [dst <addr>[/n]]
+ *   [type encode_tcp_stream|encode_ip_hdr|no_encode]
+ *
+ *   delete <rule number>
+ *
+ * Subfields can be in arbitrary order.  Port numbers and addresses
+ * must be in either numeric or symbolic form. An optional rule number
+ * is used to control the order in which rules are searched.  If two
+ * rules have the same number, then search order cannot be guaranteed,
+ * and the rules should be disjoint.  If no rule number is specified,
+ * then 0 is used, and group 0 rules are always checked before any
+ * others.
+ */
+    int i, n, len;
+    int cmd_len;
+    int token_count;
+    int state;
+    char *token;
+    char buffer[256];
+    char str_port[sizeof(buffer)];
+    char str_server_port[sizeof(buffer)];
+
+    int rule_index;
+    int proto;
+    int proxy_type;
+    int proxy_port;
+    int server_port;
+    struct in_addr server_addr;
+    struct in_addr src_addr, src_mask;
+    struct in_addr dst_addr, dst_mask;
+    struct proxy_entry *proxy_entry;
+
+/* Copy command line into a buffer */
+    cmd_len = strlen(cmd);
+    if (cmd_len > (sizeof(buffer) - 1))
+        return -1;
+    strcpy(buffer, cmd);
+
+/* Convert to lower case */
+    len = strlen(buffer);
+    for (i=0; i<len; i++)
+        buffer[i] = tolower(buffer[i]);
+
+/* Set default proxy type */
+
+/* Set up default values */
+    rule_index = 0;
+    proxy_type = PROXY_TYPE_ENCODE_NONE;
+    proto = IPPROTO_TCP;
+    proxy_port = 0;
+    server_addr.s_addr = 0;
+    server_port = 0;
+    src_addr.s_addr = 0;
+    IpMask(0, &src_mask);
+    dst_addr.s_addr = 0;
+    IpMask(0, &dst_mask);
+
+    str_port[0] = 0;
+    str_server_port[0] = 0;
+
+/* Parse command string with state machine */
+#define STATE_READ_KEYWORD    0
+#define STATE_READ_TYPE       1
+#define STATE_READ_PORT       2
+#define STATE_READ_SERVER     3
+#define STATE_READ_RULE       4
+#define STATE_READ_DELETE     5
+#define STATE_READ_PROTO      6
+#define STATE_READ_SRC        7
+#define STATE_READ_DST        8
+    state = STATE_READ_KEYWORD;
+    token = strtok(buffer, " \t");
+    token_count = 0;
+    while (token != NULL)
+    {
+        token_count++;
+        switch (state)
+        {
+        case STATE_READ_KEYWORD:
+            if (strcmp(token, "type") == 0)
+                state = STATE_READ_TYPE;
+            else if (strcmp(token, "port") == 0)
+                state = STATE_READ_PORT;
+            else if (strcmp(token, "server") == 0)
+                state = STATE_READ_SERVER;
+            else if (strcmp(token, "rule") == 0)
+                state = STATE_READ_RULE;
+            else if (strcmp(token, "delete") == 0)
+                state = STATE_READ_DELETE;
+            else if (strcmp(token, "proto") == 0)
+                state = STATE_READ_PROTO;
+            else if (strcmp(token, "src") == 0)
+                state = STATE_READ_SRC;
+            else if (strcmp(token, "dst") == 0)
+                state = STATE_READ_DST;
+            else
+                return -1;
+            break;
+
+        case STATE_READ_TYPE:
+            if (strcmp(token, "encode_ip_hdr") == 0)
+                proxy_type = PROXY_TYPE_ENCODE_IPHDR;
+            else if (strcmp(token, "encode_tcp_stream") == 0)
+                proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
+            else if (strcmp(token, "no_encode") == 0)
+                proxy_type = PROXY_TYPE_ENCODE_NONE;
+            else
+                return -1;
+            state = STATE_READ_KEYWORD;
+            break;
+
+        case STATE_READ_PORT:
+            strcpy(str_port, token);
+            state = STATE_READ_KEYWORD;
+            break;
+
+        case STATE_READ_SERVER:
+            {
+                int err;
+                char *p;
+                char s[sizeof(buffer)];
+
+                p = token;
+                while (*p != ':' && *p != 0)
+                    p++;
+
+                if (*p != ':')
+                {
+                    err = IpAddr(token, &server_addr);
+                    if (err)
+                        return -1;
+                }
+                else
+                {
+                    *p = ' ';
+                
+                    n = sscanf(token, "%s %s", s, str_server_port);
+                    if (n != 2)
+                        return -1;
+
+                    err = IpAddr(s, &server_addr);
+                    if (err)
+                        return -1;
+                }
+            }
+            state = STATE_READ_KEYWORD;
+            break;
+
+        case STATE_READ_RULE:
+            n = sscanf(token, "%d", &rule_index);
+            if (n != 1 || rule_index < 0)
+                return -1;
+            state = STATE_READ_KEYWORD;
+            break;
+
+        case STATE_READ_DELETE:
+            {
+                int err;
+                int rule_to_delete;
+
+                if (token_count != 2)
+                    return -1;
+
+                n = sscanf(token, "%d", &rule_to_delete);
+                if (n != 1)
+                    return -1;
+                err = RuleNumberDelete(rule_to_delete);
+                if (err)
+                    return -1;
+                return 0;
+            }
+
+        case STATE_READ_PROTO:
+            if (strcmp(token, "tcp") == 0)
+                proto = IPPROTO_TCP;
+            else if (strcmp(token, "udp") == 0)
+                proto = IPPROTO_UDP;
+            else
+                return -1;
+            state = STATE_READ_KEYWORD;
+            break;
+
+        case STATE_READ_SRC:
+        case STATE_READ_DST:
+            {
+                int err;
+                char *p;
+                struct in_addr mask;
+                struct in_addr addr;
+
+                p = token;
+                while (*p != '/' && *p != 0)
+                    p++;
+
+                if (*p != '/')
+                {
+                     IpMask(32, &mask);
+                     err = IpAddr(token, &addr);
+                     if (err)
+                         return -1;
+                }
+                else
+                {
+                    int n;
+                    int nbits;
+                    char s[sizeof(buffer)];
+
+                    *p = ' ';
+                    n = sscanf(token, "%s %d", s, &nbits);
+                    if (n != 2)
+                        return -1;
+
+                    err = IpAddr(s, &addr);
+                    if (err)
+                        return -1;
+
+                    err = IpMask(nbits, &mask);
+                    if (err)
+                        return -1;
+                }
+
+                if (state == STATE_READ_SRC)
+                {
+                    src_addr = addr;
+                    src_mask = mask;
+                }
+                else 
+                {
+                    dst_addr = addr;
+                    dst_mask = mask;
+                }
+            }
+            state = STATE_READ_KEYWORD;
+            break;
+
+        default:
+            return -1;
+            break;
+        }
+
+        token = strtok(NULL, " \t");
+    }
+#undef STATE_READ_KEYWORD
+#undef STATE_READ_TYPE
+#undef STATE_READ_PORT
+#undef STATE_READ_SERVER
+#undef STATE_READ_RULE
+#undef STATE_READ_DELETE
+#undef STATE_READ_PROTO
+#undef STATE_READ_SRC
+#undef STATE_READ_DST
+
+/* Convert port strings to numbers.  This needs to be done after
+   the string is parsed, because the prototype might not be designated
+   before the ports (which might be symbolic entries in /etc/services) */
+
+    if (strlen(str_port) != 0)
+    {
+        int err;
+
+        err = IpPort(str_port, proto, &proxy_port);
+        if (err)
+            return -1;
+    }
+    else
+    {
+        proxy_port = 0;
+    }
+
+    if (strlen(str_server_port) != 0)
+    { 
+        int err;
+
+        err = IpPort(str_server_port, proto, &server_port);
+        if (err)
+            return -1;
+    }
+    else
+    {
+        server_port = 0;
+    }
+
+/* Check that at least the server address has been defined */
+    if (server_addr.s_addr == 0)
+        return -1;
+
+/* Add to linked list */
+    proxy_entry = malloc(sizeof(struct proxy_entry));
+    if (proxy_entry == NULL)
+        return -1;
+
+    proxy_entry->proxy_type = proxy_type;
+    proxy_entry->rule_index = rule_index;
+    proxy_entry->proto = proto;
+    proxy_entry->proxy_port = htons(proxy_port);
+    proxy_entry->server_port = htons(server_port);
+    proxy_entry->server_addr = server_addr;
+    proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
+    proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
+    proxy_entry->src_mask = src_mask;
+    proxy_entry->dst_mask = dst_mask;
+
+    RuleAdd(proxy_entry);
+
+    return 0;
+}
diff --git a/alias/alias_util.c b/alias/alias_util.c
new file mode 100644 (file)
index 0000000..fe07653
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+    Alias_util.h contains general utilities used by other functions
+    in the packet aliasing module.  At the moment, there are functions
+    for computing IP header and TCP packet checksums.
+
+    The checksum routines are based upon example code in a Unix networking
+    text written by Stevens (sorry, I can't remember the title -- but
+    at least this is a good author).
+
+    Initial Version:  August, 1996  (cjm)
+
+    Version 1.7:  January 9, 1997
+         Added differential checksum update function.
+*/
+
+/*
+Note: the checksum routines assume that the actual checksum word has
+been zeroed out.  If the checksum workd is filled with the proper value,
+then these routines will give a result of zero (useful for testing
+purposes);
+*/
+    
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "alias.h"
+#include "alias_local.h"
+
+u_short
+PacketAliasInternetChecksum(u_short *ptr, int nbytes)
+{
+    int sum, oddbyte;
+
+    sum = 0;
+    while (nbytes > 1)
+    {
+        sum += *ptr++;
+        nbytes -= 2;
+    }
+    if (nbytes == 1)
+    {
+        oddbyte = 0;
+        *((u_char *) &oddbyte) = *(u_char *) ptr;
+        sum += oddbyte;
+    }
+    sum = (sum >> 16) + (sum & 0xffff);
+    sum += (sum >> 16);
+    return(~sum);
+}
+
+u_short
+IpChecksum(struct ip *pip)
+{
+    return( PacketAliasInternetChecksum((u_short *) pip,
+            (pip->ip_hl << 2)) );
+
+}
+
+u_short 
+TcpChecksum(struct ip *pip)
+{
+    u_short *ptr;
+    struct tcphdr *tc;
+    int nhdr, ntcp, nbytes;
+    int sum, oddbyte;
+
+    nhdr = pip->ip_hl << 2;
+    ntcp = ntohs(pip->ip_len) - nhdr;
+
+    tc = (struct tcphdr *) ((char *) pip + nhdr);
+    ptr = (u_short *) tc;
+    
+/* Add up TCP header and data */
+    nbytes = ntcp;
+    sum = 0;
+    while (nbytes > 1)
+    {
+        sum += *ptr++;
+        nbytes -= 2;
+    }
+    if (nbytes == 1)
+    {
+        oddbyte = 0;
+        *((u_char *) &oddbyte) = *(u_char *) ptr;
+        sum += oddbyte;
+    }
+
+/* "Pseudo-header" data */
+    ptr = (u_short *) &(pip->ip_dst);
+    sum += *ptr++;
+    sum += *ptr;
+    ptr = (u_short *) &(pip->ip_src);
+    sum += *ptr++;
+    sum += *ptr;
+    sum += htons((u_short) ntcp);
+    sum += htons((u_short) pip->ip_p);
+
+/* Roll over carry bits */
+    sum = (sum >> 16) + (sum & 0xffff);
+    sum += (sum >> 16);
+
+/* Return checksum */
+    return((u_short) ~sum);
+}
+
+
+void
+DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
+{
+    int i;
+    int accumulate;
+
+    accumulate = *cksum;
+    for (i=0; i<n; i++)
+    {
+        accumulate -= *new++;
+        accumulate += *old++;
+    }
+
+    if (accumulate < 0)
+    {
+        accumulate = -accumulate;
+        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
+        accumulate += accumulate >> 16;
+        *cksum = (u_short) ~accumulate;
+    }
+    else
+    {
+        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
+        accumulate += accumulate >> 16;
+        *cksum = (u_short) accumulate;
+    }
+}
+
diff --git a/arp.tproj/Makefile b/arp.tproj/Makefile
new file mode 100644 (file)
index 0000000..50e5151
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = arp
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = arp.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble arp4.4 arp.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/arp.tproj/Makefile.postamble b/arp.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..3b11434
--- /dev/null
@@ -0,0 +1,115 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
+
+beforeinstall:
+       install -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} arp4.0 \
+           ${DESTDIR}${MANDIR}4/arp.0
+
diff --git a/arp.tproj/Makefile.preamble b/arp.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..c7802b8
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+#OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = arp4.0
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/arp.tproj/PB.project b/arp.tproj/PB.project
new file mode 100644 (file)
index 0000000..237a43f
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (arp.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, arp4.4, arp.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = arp; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/arp.tproj/arp.8 b/arp.tproj/arp.8
new file mode 100644 (file)
index 0000000..313aba2
--- /dev/null
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)arp.8      8.2 (Berkeley) 4/27/95
+.\"
+.Dd April 27, 1995
+.Dt ARP 8
+.Os BSD 4.3
+.Sh NAME
+.Nm arp
+.Nd address resolution display and control
+.Sh SYNOPSIS
+.Nm arp
+.Ar hostname
+.Nm arp
+.Fl a
+.Nm arp
+.Fl d Ar hostname
+.Nm arp
+.Fl s Ar hostname ether_addr
+.Op Ar temp
+.Op Ar pub
+.Nm arp
+.Fl f Ar filename
+.Sh DESCRIPTION
+The
+.Nm arp
+program displays and modifies the Internet-to-Ethernet address translation
+tables used by the address resolution protocol
+.Pq Xr arp 4 .
+With no flags, the program displays the current
+.Tn ARP
+entry for
+.Ar hostname .
+The host may be specified by name or by number,
+using Internet dot notation.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+The program displays all of the current
+.Tn ARP
+entries.
+.It Fl d
+A super-user may delete an entry for the host called
+.Ar hostname
+with the
+.Fl d
+flag.
+.It Fl s Ar hostname ether_addr
+Create an
+.Tn ARP
+entry for the host called
+.Ar hostname
+with the Ethernet address 
+.Ar ether_addr .
+The Ethernet address is given as six hex bytes separated by colons.
+The entry will be permanent unless the word
+.Ar temp
+is given in the command. 
+If the word
+.Ar pub
+is given, the entry will be "published"; i.e., this system will
+act as an
+.Tn ARP
+server,
+responding to requests for 
+.Ar hostname
+even though the host address is not its own.
+.It Fl f
+Causes the file
+.Ar filename
+to be read and multiple entries to be set in the
+.Tn ARP
+tables.  Entries
+in the file should be of the form
+.Pp
+.Bd -filled -offset indent -compact
+.Ar hostname ether_addr
+.Op Ar temp
+.Op Ar pub
+.Ed
+.Pp
+with argument meanings as given above.
+.El
+.Sh SEE ALSO
+.Xr inet 3 ,
+.Xr arp 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/arp.tproj/arp.c b/arp.tproj/arp.c
new file mode 100644 (file)
index 0000000..4e932b4
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1984, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Sun Microsystems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1984, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)arp.c      8.3 (Berkeley) 4/28/95";
+#endif /* not lint */
+
+/*
+ * arp - display, set, and delete arp table entries
+ */
+
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int pid;
+static int nflag;
+static int s = -1;
+
+int    delete __P((char *, char *));
+void   dump __P((u_long));
+int    ether_aton __P((char *, u_char *));
+void   ether_print __P((u_char *));
+int    file __P((char *));
+void   get __P((char *));
+void   getsocket __P((void));
+int    rtmsg __P((int));
+int    set __P((int, char **));
+void   usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       int ch;
+
+       pid = getpid();
+       while ((ch = getopt(argc, argv, "ands")) != EOF)
+               switch((char)ch) {
+               case 'a':
+                       dump(0);
+                       exit(0);
+               case 'd':
+                       if (argc < 3 || argc > 4)
+                               usage();
+                       delete(argv[2], argv[3]);
+                       exit(0);
+               case 'n':
+                       nflag = 1;
+                       continue;
+               case 's':
+                       if (argc < 4 || argc > 7)
+                               usage();
+                       exit(set(argc-2, &argv[2]) ? 1 : 0);
+               case '?':
+               default:
+                       usage();
+               }
+       if (argc != 2)
+               usage();
+       get(argv[1]);
+       return (0);
+}
+
+/*
+ * Process a file to set standard arp entries
+ */
+int
+file(name)
+       char *name;
+{
+       FILE *fp;
+       int i, retval;
+       char line[100], arg[5][50], *args[5];
+
+       if ((fp = fopen(name, "r")) == NULL) {
+               fprintf(stderr, "arp: cannot open %s\n", name);
+               exit(1);
+       }
+       args[0] = &arg[0][0];
+       args[1] = &arg[1][0];
+       args[2] = &arg[2][0];
+       args[3] = &arg[3][0];
+       args[4] = &arg[4][0];
+       retval = 0;
+       while(fgets(line, 100, fp) != NULL) {
+               i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
+                   arg[3], arg[4]);
+               if (i < 2) {
+                       fprintf(stderr, "arp: bad line: %s\n", line);
+                       retval = 1;
+                       continue;
+               }
+               if (set(i, args))
+                       retval = 1;
+       }
+       fclose(fp);
+       return (retval);
+}
+
+void
+getsocket() {
+       if (s < 0) {
+               s = socket(PF_ROUTE, SOCK_RAW, 0);
+               if (s < 0) {
+                       perror("arp: socket");
+                       exit(1);
+               }
+       }
+}
+
+struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
+struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
+struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
+int    expire_time, flags, export_only, doing_proxy, found_entry;
+struct {
+       struct  rt_msghdr m_rtm;
+       char    m_space[512];
+}      m_rtmsg;
+
+/*
+ * Set an individual arp entry 
+ */
+int
+set(argc, argv)
+       int argc;
+       char **argv;
+{
+       struct hostent *hp;
+       register struct sockaddr_inarp *sin = &sin_m;
+       register struct sockaddr_dl *sdl;
+       register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
+       u_char *ea;
+       char *host = argv[0], *eaddr = argv[1];
+
+       getsocket();
+       argc -= 2;
+       argv += 2;
+       sdl_m = blank_sdl;
+       sin_m = blank_sin;
+       sin->sin_addr.s_addr = inet_addr(host);
+       if (sin->sin_addr.s_addr == -1) {
+               if (!(hp = gethostbyname(host))) {
+                       fprintf(stderr, "arp: %s: ", host);
+                       herror((char *)NULL);
+                       return (1);
+               }
+               bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
+                   sizeof sin->sin_addr);
+       }
+       ea = (u_char *)LLADDR(&sdl_m);
+       if (ether_aton(eaddr, ea) == 0)
+               sdl_m.sdl_alen = 6;
+       doing_proxy = flags = export_only = expire_time = 0;
+       while (argc-- > 0) {
+               if (strncmp(argv[0], "temp", 4) == 0) {
+                       struct timeval time;
+                       gettimeofday(&time, 0);
+                       expire_time = time.tv_sec + 20 * 60;
+               }
+               else if (strncmp(argv[0], "pub", 3) == 0) {
+                       flags |= RTF_ANNOUNCE;
+                       doing_proxy = SIN_PROXY;
+               } else if (strncmp(argv[0], "trail", 5) == 0) {
+                       printf("%s: Sending trailers is no longer supported\n",
+                               host);
+               }
+               argv++;
+       }
+tryagain:
+       if (rtmsg(RTM_GET) < 0) {
+               perror(host);
+               return (1);
+       }
+       sin = (struct sockaddr_inarp *)(rtm + 1);
+       sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
+       if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
+               if (sdl->sdl_family == AF_LINK &&
+                   (rtm->rtm_flags & RTF_LLINFO) &&
+                   !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
+               case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
+               case IFT_ISO88024: case IFT_ISO88025:
+                       goto overwrite;
+               }
+               if (doing_proxy == 0) {
+                       printf("set: can only proxy for %s\n", host);
+                       return (1);
+               }
+               if (sin_m.sin_other & SIN_PROXY) {
+                       printf("set: proxy entry exists for non 802 device\n");
+                       return(1);
+               }
+               sin_m.sin_other = SIN_PROXY;
+               export_only = 1;
+               goto tryagain;
+       }
+overwrite:
+       if (sdl->sdl_family != AF_LINK) {
+               printf("cannot intuit interface index and type for %s\n", host);
+               return (1);
+       }
+       sdl_m.sdl_type = sdl->sdl_type;
+       sdl_m.sdl_index = sdl->sdl_index;
+       return (rtmsg(RTM_ADD));
+}
+
+/*
+ * Display an individual arp entry
+ */
+void
+get(host)
+       char *host;
+{
+       struct hostent *hp;
+       struct sockaddr_inarp *sin = &sin_m;
+
+       sin_m = blank_sin;
+       sin->sin_addr.s_addr = inet_addr(host);
+       if (sin->sin_addr.s_addr == -1) {
+               if (!(hp = gethostbyname(host))) {
+                       fprintf(stderr, "arp: %s: ", host);
+                       herror((char *)NULL);
+                       exit(1);
+               }
+               bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
+                   sizeof sin->sin_addr);
+       }
+       dump(sin->sin_addr.s_addr);
+       if (found_entry == 0) {
+               printf("%s (%s) -- no entry\n",
+                   host, inet_ntoa(sin->sin_addr));
+               exit(1);
+       }
+}
+
+/*
+ * Delete an arp entry 
+ */
+int
+delete(host, info)
+       char *host;
+       char *info;
+{
+       struct hostent *hp;
+       register struct sockaddr_inarp *sin = &sin_m;
+       register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
+       struct sockaddr_dl *sdl;
+
+       if (info && strncmp(info, "pro", 3) )
+               export_only = 1;
+       getsocket();
+       sin_m = blank_sin;
+       sin->sin_addr.s_addr = inet_addr(host);
+       if (sin->sin_addr.s_addr == -1) {
+               if (!(hp = gethostbyname(host))) {
+                       fprintf(stderr, "arp: %s: ", host);
+                       herror((char *)NULL);
+                       return (1);
+               }
+               bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
+                   sizeof sin->sin_addr);
+       }
+tryagain:
+       if (rtmsg(RTM_GET) < 0) {
+               perror(host);
+               return (1);
+       }
+       sin = (struct sockaddr_inarp *)(rtm + 1);
+       sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
+       if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
+               if (sdl->sdl_family == AF_LINK &&
+                   (rtm->rtm_flags & RTF_LLINFO) &&
+                   !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
+               case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
+               case IFT_ISO88024: case IFT_ISO88025:
+                       goto delete;
+               }
+       }
+       if (sin_m.sin_other & SIN_PROXY) {
+               fprintf(stderr, "delete: can't locate %s\n",host);
+               return (1);
+       } else {
+               sin_m.sin_other = SIN_PROXY;
+               goto tryagain;
+       }
+delete:
+       if (sdl->sdl_family != AF_LINK) {
+               printf("cannot locate %s\n", host);
+               return (1);
+       }
+       if (rtmsg(RTM_DELETE))
+               return (1);
+       printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
+       return (0);
+}
+
+/*
+ * Dump the entire arp table
+ */
+void
+dump(addr)
+       u_long addr;
+{
+       int mib[6];
+       size_t needed;
+       char *host, *lim, *buf, *next;
+       struct rt_msghdr *rtm;
+       struct sockaddr_inarp *sin;
+       struct sockaddr_dl *sdl;
+       extern int h_errno;
+       struct hostent *hp;
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;
+       mib[3] = AF_INET;
+       mib[4] = NET_RT_FLAGS;
+       mib[5] = RTF_LLINFO;
+       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+               err(1, "route-sysctl-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               err(1, "malloc");
+       if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+               err(1, "actual retrieval of routing table");
+       lim = buf + needed;
+       for (next = buf; next < lim; next += rtm->rtm_msglen) {
+               rtm = (struct rt_msghdr *)next;
+               sin = (struct sockaddr_inarp *)(rtm + 1);
+               sdl = (struct sockaddr_dl *)(sin + 1);
+               if (addr) {
+                       if (addr != sin->sin_addr.s_addr)
+                               continue;
+                       found_entry = 1;
+               }
+               if (nflag == 0)
+                       hp = gethostbyaddr((caddr_t)&(sin->sin_addr),
+                           sizeof sin->sin_addr, AF_INET);
+               else
+                       hp = 0;
+               if (hp)
+                       host = hp->h_name;
+               else {
+                       host = "?";
+                       if (h_errno == TRY_AGAIN)
+                               nflag = 1;
+               }
+               printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
+               if (sdl->sdl_alen)
+                       ether_print((u_char *)LLADDR(sdl));
+               else
+                       printf("(incomplete)");
+               if (rtm->rtm_rmx.rmx_expire == 0)
+                       printf(" permanent");
+               if (sin->sin_other & SIN_PROXY)
+                       printf(" published (proxy only)");
+               if (rtm->rtm_addrs & RTA_NETMASK) {
+                       sin = (struct sockaddr_inarp *)
+                               (sdl->sdl_len + (char *)sdl);
+                       if (sin->sin_addr.s_addr == 0xffffffff)
+                               printf(" published");
+                       if (sin->sin_len != 8)
+                               printf("(wierd)");
+               }
+               printf("\n");
+       }
+}
+
+void
+ether_print(cp)
+       u_char *cp;
+{
+       printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
+}
+
+int
+ether_aton(a, n)
+       char *a;
+       u_char *n;
+{
+       int i, o[6];
+
+       i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
+                                          &o[3], &o[4], &o[5]);
+       if (i != 6) {
+               fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
+               return (1);
+       }
+       for (i=0; i<6; i++)
+               n[i] = o[i];
+       return (0);
+}
+
+void
+usage()
+{
+       printf("usage: arp hostname\n");
+       printf("       arp -a [kernel] [kernel_memory]\n");
+       printf("       arp -d hostname\n");
+       printf("       arp -s hostname ether_addr [temp] [pub]\n");
+       printf("       arp -f filename\n");
+       exit(1);
+}
+
+int
+rtmsg(cmd)
+       int cmd;
+{
+       static int seq;
+       int rlen;
+       register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
+       register char *cp = m_rtmsg.m_space;
+       register int l;
+
+       errno = 0;
+       if (cmd == RTM_DELETE)
+               goto doit;
+       bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
+       rtm->rtm_flags = flags;
+       rtm->rtm_version = RTM_VERSION;
+
+       switch (cmd) {
+       default:
+               fprintf(stderr, "arp: internal wrong cmd\n");
+               exit(1);
+       case RTM_ADD:
+               rtm->rtm_addrs |= RTA_GATEWAY;
+               rtm->rtm_rmx.rmx_expire = expire_time;
+               rtm->rtm_inits = RTV_EXPIRE;
+               rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
+               sin_m.sin_other = 0;
+               if (doing_proxy) {
+                       if (export_only)
+                               sin_m.sin_other = SIN_PROXY;
+                       else {
+                               rtm->rtm_addrs |= RTA_NETMASK;
+                               rtm->rtm_flags &= ~RTF_HOST;
+                       }
+               }
+               /* FALLTHROUGH */
+       case RTM_GET:
+               rtm->rtm_addrs |= RTA_DST;
+       }
+#define NEXTADDR(w, s) \
+       if (rtm->rtm_addrs & (w)) { \
+               bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
+
+       NEXTADDR(RTA_DST, sin_m);
+       NEXTADDR(RTA_GATEWAY, sdl_m);
+       NEXTADDR(RTA_NETMASK, so_mask);
+
+       rtm->rtm_msglen = cp - (char *)&m_rtmsg;
+doit:
+       l = rtm->rtm_msglen;
+       rtm->rtm_seq = ++seq;
+       rtm->rtm_type = cmd;
+       if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
+               if (errno != ESRCH || cmd != RTM_DELETE) {
+                       perror("writing to routing socket");
+                       return (-1);
+               }
+       }
+       do {
+               l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+       } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
+       if (l < 0)
+               (void) fprintf(stderr, "arp: read from routing socket: %s\n",
+                   strerror(errno));
+       return (0);
+}
diff --git a/arp.tproj/arp4.4 b/arp.tproj/arp4.4
new file mode 100644 (file)
index 0000000..0cd7161
--- /dev/null
@@ -0,0 +1,124 @@
+.\" Copyright (c) 1985, 1986, 1988, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)arp4.4      6.5 (Berkeley) 4/18/94
+.\"
+.Dd April 18, 1994
+.Dt ARP 4
+.Os BSD 4
+.Sh NAME
+.Nm arp
+.Nd Address Resolution Protocol
+.Sh SYNOPSIS
+.Em "pseudo-device ether"
+.Sh DESCRIPTION
+The Address Resolution Protocol (ARP) is a protocol used to dynamically
+map between Internet host addresses and 10Mb/s Ethernet addresses.
+It is used by all the 10Mb/s Ethernet interface drivers.
+It is not specific to Internet protocols or to 10Mb/s Ethernet,
+but this implementation currently supports only that combination.
+.Pp
+ARP caches Internet-Ethernet address mappings. 
+When an interface requests a mapping for an address not in the cache,
+ARP queues the message which requires the mapping and broadcasts
+a message on the associated network requesting the address mapping.
+If a response is provided, the new mapping is cached and any pending
+message is transmitted.
+ARP will queue at most one packet while waiting for a response to a
+mapping request;
+only the most recently ``transmitted'' packet is kept.
+If the target host does not respond after several requests,
+the host is considered to be down for a short period (normally 20 seconds),
+allowing an error to be returned to transmission attempts during this
+interval.
+The error is
+.Li EHOSTDOWN
+for a non-responding destination host, and
+.Li EHOSTUNREACH
+for a non-responding router.
+.Pp
+The ARP cache is stored in the system routing table as
+dynamically-created host routes.
+The route to a directly-attached Ethernet network is installed as a
+.Dq cloning
+route (one with the
+.Li RTF_CLONING
+flag set),
+causing routes to individual hosts on that network to be created on
+demand.
+These routes time out periodically (normally 20 minutes after validated;
+entries are not validated when not in use).
+An entry for a host which is not responding is a
+.Dq reject
+route (one with the
+.Li RTF_REJECT
+flag set).
+.Pp
+ARP entries may be added, deleted or changed with the
+.Xr arp 8
+utility.
+Manually-added entries may be temporary or permanent,
+and may be
+.Dq published ,
+in which case the system will respond to ARP requests for that host
+as if it were the target of the request.
+.Pp
+In the past,
+ARP was used to negotiate the use of a trailer encapsulation.
+This is no longer supported.
+.Pp
+ARP watches passively for hosts impersonating the local host (i.e. a host
+which responds to an ARP mapping request for the local host's address).
+.Sh DIAGNOSTICS
+.Em "duplicate IP address %x!! sent from ethernet address: %x:%x:%x:%x:%x:%x."
+ARP has discovered another host on the local network which responds to
+mapping requests for its own Internet address with a different Ethernet
+address, generally indicating that two hosts are attempting to use the
+same Internet address.
+.Sh SEE ALSO
+.Xr inet 4 ,
+.Xr route 4 ,
+.Xr arp 8 ,
+.Xr ifconfig 8 ,
+.Xr route 8
+.sp
+.Rs
+.%A Plummer, D.
+.%B "An Ethernet Address Resolution Protocol"
+.%T RFC826
+.Re
+.Rs
+.%A Leffler, S.J.
+.%A Karels, M.J.
+.%B "Trailer Encapsulations
+.%T RFC893
+.Re
+
diff --git a/bootparams/Makefile b/bootparams/Makefile
new file mode 100644 (file)
index 0000000..8e40018
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = bootparams
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Aggregate
+
+TOOLS = bootparamd.tproj bpwhoami.tproj
+
+LIBRARIES = bootparams
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = aggregate.make
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/bootparams/Makefile.postamble b/bootparams/Makefile.postamble
new file mode 100644 (file)
index 0000000..411cde6
--- /dev/null
@@ -0,0 +1,100 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/bootparams/Makefile.preamble b/bootparams/Makefile.preamble
new file mode 100644 (file)
index 0000000..0bf1e82
--- /dev/null
@@ -0,0 +1,138 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+OTHER_GARBAGE = *~
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+# DSTROOT = $(HOME)
diff --git a/bootparams/PB.project b/bootparams/PB.project
new file mode 100644 (file)
index 0000000..631206a
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        H_FILES = (); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        SUBPROJECTS = (bootparams, bootparamd.tproj, bpwhoami.tproj); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = bootparams; 
+    PROJECTTYPE = Aggregate; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/bootparams/bootparamd.tproj/Makefile b/bootparams/bootparamd.tproj/Makefile
new file mode 100644 (file)
index 0000000..ae0309c
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = bootparamd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = bootparamd.c bootparam_proc.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/bootparams/bootparamd.tproj/Makefile.postamble b/bootparams/bootparamd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..411cde6
--- /dev/null
@@ -0,0 +1,100 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/bootparams/bootparamd.tproj/Makefile.preamble b/bootparams/bootparamd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..db3f4e7
--- /dev/null
@@ -0,0 +1,140 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+OTHER_GARBAGE = *~
+OTHER_LIBS = -lbootparams
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+# DSTROOT = $(HOME)
+
diff --git a/bootparams/bootparamd.tproj/PB.project b/bootparams/bootparamd.tproj/PB.project
new file mode 100644 (file)
index 0000000..89f2397
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (bootparamd.c, bootparam_proc.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_INSTALLDIR = /bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = bootparamd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = /Library/Executables; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/bootparams/bootparamd.tproj/bootparam_proc.c b/bootparams/bootparamd.tproj/bootparam_proc.c
new file mode 100644 (file)
index 0000000..faa0ff3
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * BOOTPARAMS server
+ * Copyright 1998, Apple Computer Inc.  Unpublished.
+ *
+ * Written by Marc Majka
+ */
+
+#include <rpc/rpc.h>
+#include "bootparam_prot.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <bootparams.h>
+#include <syslog.h>
+
+extern int debug;
+extern unsigned long route_addr;
+extern char domain_name[];
+
+struct hostent *h;
+static char hostname[MAXHOSTNAMELEN];
+
+bp_whoami_res *
+bootparamproc_whoami_1_svc(whoami, req)
+bp_whoami_arg *whoami;
+struct svc_req *req;
+{
+       long haddr;
+       static bp_whoami_res res;
+       struct bootparamsent *bp;
+
+       if (debug)
+       {
+               fprintf(stderr,"whoami %d.%d.%d.%d\n", 
+                       255 & whoami->client_address.bp_address_u.ip_addr.net,
+                       255 & whoami->client_address.bp_address_u.ip_addr.host,
+                       255 & whoami->client_address.bp_address_u.ip_addr.lh,
+                       255 & whoami->client_address.bp_address_u.ip_addr.impno);
+       }
+
+       bcopy((char *)&whoami->client_address.bp_address_u.ip_addr,
+               (char *)&haddr, sizeof(haddr));
+       h = gethostbyaddr((char *)&haddr, sizeof(haddr), AF_INET);
+       if (h == NULL)
+       {
+               if (debug) fprintf(stderr,"whoami failed: gethostbyaddr\n");
+               return NULL;
+       }
+
+       /* check whether subsequent bpgetfile requests would succeed */
+       bp = bootparams_getbyname(h->h_name);
+       if (bp == NULL) {
+               if (debug) 
+                   fprintf(stderr, "whoami failed: bootparams_getbyname\n");
+               return NULL;
+       }
+
+       sprintf(hostname, "%s", h->h_name);
+       res.client_name = hostname;
+
+       res.domain_name = domain_name;
+
+       res.router_address.address_type = IP_ADDR_TYPE;
+       bcopy(&route_addr, &res.router_address.bp_address_u.ip_addr, 4);
+
+       if (debug)
+       {
+               fprintf(stderr, "whoami name=%s domain=%s router=%d.%d.%d.%d\n", 
+                       res.client_name,
+                       res.domain_name,
+                       255 & res.router_address.bp_address_u.ip_addr.net,
+                       255 & res.router_address.bp_address_u.ip_addr.host,
+                       255 & res.router_address.bp_address_u.ip_addr.lh,
+                       255 & res.router_address.bp_address_u.ip_addr.impno);
+       }
+
+       return (&res);
+}
+
+bp_getfile_res *
+bootparamproc_getfile_1_svc(getfile, req)
+bp_getfile_arg *getfile;
+struct svc_req *req;
+{
+       static bp_getfile_res res;
+       struct bootparamsent *bp;
+       static char s[1024];
+       char *p;
+       int i, len;
+
+       if (debug)
+       {
+               fprintf(stderr, "getfile %s %s\n",
+                       getfile->client_name, getfile->file_id);
+       }
+
+       bp = bootparams_getbyname(getfile->client_name);
+       if (bp == NULL)
+       {
+               if (debug)
+               {
+                       fprintf(stderr, "can't find bootparams for %s\n",
+                               getfile->client_name);
+                       fprintf(stderr, "getfile failed\n");
+               }
+               return NULL;
+       }
+
+       len = strlen(getfile->file_id) + 1;
+       sprintf(s, "%s=", getfile->file_id);
+
+       for (i = 0; bp->bp_bootparams[i] != NULL; i++)
+       {
+               if (!strncmp(s, bp->bp_bootparams[i], len)) break;
+       }
+
+       if (bp->bp_bootparams[i] == NULL)
+       {
+               if (debug)
+               {
+                       fprintf(stderr, "can't find bootparam %s\n", getfile->file_id);
+                       fprintf(stderr, "getfile failed\n");
+               }
+               return NULL;
+       }
+
+       sprintf(s, bp->bp_bootparams[i] + len);
+       p = strchr(s, ':');
+       if (p == NULL)
+       {
+               hostname[0] = '\0';
+               res.server_name = hostname;
+               res.server_address.bp_address_u.ip_addr.net = 0;
+               res.server_address.bp_address_u.ip_addr.host = 0;
+               res.server_address.bp_address_u.ip_addr.lh = 0;
+               res.server_address.bp_address_u.ip_addr.impno = 0;
+               res.server_address.address_type = 1;
+               res.server_path = s;
+
+               if (debug)
+               {
+                fprintf(stderr, "getfile server=%s (%d.%d.%d.%d) path=%s\n",
+                          res.server_name,
+                          255 & res.server_address.bp_address_u.ip_addr.net,
+                          255 & res.server_address.bp_address_u.ip_addr.host,
+                         255 & res.server_address.bp_address_u.ip_addr.lh,
+                         255 & res.server_address.bp_address_u.ip_addr.impno,
+                               res.server_path);
+               }
+               return (&res);
+       }
+
+       *p = '\0';
+       p++;
+       h = gethostbyname(s);
+       if (h == NULL)
+       {
+               if (debug)
+               {
+                       fprintf(stderr, "can't find server %s\n", s);
+                       fprintf(stderr, "getfile failed\n");
+               }
+               return NULL;
+       }
+
+       res.server_name = s;
+       res.server_path = p;
+       bcopy(h->h_addr, &res.server_address.bp_address_u.ip_addr, h->h_length);
+       res.server_address.address_type = IP_ADDR_TYPE;
+
+    if (debug)
+       {
+      fprintf(stderr, "getfile server=%s (%d.%d.%d.%d) path=%s\n",
+            res.server_name,
+            255 & res.server_address.bp_address_u.ip_addr.net,
+            255 & res.server_address.bp_address_u.ip_addr.host,
+            255 & res.server_address.bp_address_u.ip_addr.lh,
+            255 & res.server_address.bp_address_u.ip_addr.impno,
+               res.server_path);
+       }
+
+    return (&res);
+}
diff --git a/bootparams/bootparamd.tproj/bootparamd.c b/bootparams/bootparamd.tproj/bootparamd.c
new file mode 100644 (file)
index 0000000..e76bd42
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * BOOTPARAMS server
+ * Copyright 1998, Apple Computer Inc.  Unpublished.
+ *
+ * Written by Marc Majka
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include "bootparam_prot.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int debug = 0;
+char *progname;
+
+unsigned long route_addr;
+char domain_name[MAXHOSTNAMELEN];
+
+int _rpcsvcdirty;
+extern void bootparamprog_1();
+
+extern int getdomainname(char*, int);
+
+void
+usage(void)
+{
+       fprintf(stderr, "usage: %s [-d] [-r router]\n", progname);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       SVCXPRT *transp;
+       int i;
+       struct hostent *h;
+       char str[256];
+       FILE *fp;
+       
+       progname = strrchr(argv[0],'/');
+       if (progname) progname++;
+       else progname = argv[0];
+
+       route_addr = 0;
+
+       for (i = 1; i < argc; i++)
+       {
+               if (!strcmp(argv[i], "-d"))
+               {
+                       debug = 1;
+               }
+               else if (!strcmp(argv[i], "-r"))
+               {
+                       i++;
+                       if (i >= argc) usage();
+
+                       route_addr = inet_addr(argv[i]);
+                       if (route_addr == -1)
+                       {
+                               h = gethostbyname(argv[i]);
+                               if (h == NULL)
+                               {
+                                       fprintf(stderr, "%s: Can't find host %s\n",
+                                               progname, argv[i]);
+                                       exit(1);
+                               }
+
+                               bcopy(h->h_addr, (char *)&route_addr, sizeof(route_addr));
+                       }
+               }
+               else usage();
+       }
+
+       if (route_addr == 0)
+       {
+               fp = popen("/usr/sbin/netstat -r -n", "r");
+               while (NULL != fgets(str, 256, fp))
+               {
+                       if (strncmp(str, "default ", 8)) continue;
+                       if (!strncmp(str + 17, "link", 4)) continue;
+                       route_addr = inet_addr(str+17);
+                       break;
+               }
+               pclose(fp);
+       }
+
+       domain_name[0] = '\0';
+       if (getdomainname(domain_name, sizeof(domain_name)) != 0)
+           domain_name[0] = '\0';
+
+       if (debug == 0) daemon(0,0);            
+
+       openlog(progname, 0, LOG_DAEMON);
+       pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS);
+
+       transp = svcudp_create(RPC_ANYSOCK);
+       if (transp == NULL)
+       {
+               syslog(LOG_ERR, "Can't create udp service.");
+               exit(1);
+       }
+
+       if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, IPPROTO_UDP))
+       {
+               syslog(LOG_ERR, "Can't register service.");
+               exit(1);
+       }
+
+       svc_run();
+       
+       syslog(LOG_ERR, "svc_run returned");
+       exit(1);
+}
+
+
diff --git a/bootparams/bootparams/Makefile b/bootparams/bootparams/Makefile
new file mode 100644 (file)
index 0000000..931d5c9
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = bootparams
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Library
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
+            bootparam_prot.x
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CURRENTLY_ACTIVE_VERSION = YES
+DEPLOY_WITH_VERSION_NAME = A
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = library.make
+NEXTSTEP_INSTALLDIR = /usr/local/lib
+WINDOWS_INSTALLDIR = /Developer/Libraries
+PDO_UNIX_INSTALLDIR = /lib
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+WINDOWS_PUBLIC_HEADERS_DIR = $(HOMEDRIVE)$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)
+
+PDO_UNIX_PUBLIC_HEADERS_DIR = $(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/bootparams/bootparams/Makefile.postamble b/bootparams/bootparams/Makefile.postamble
new file mode 100644 (file)
index 0000000..a939e58
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Needed since a .x file in Other Sources will require a corresponding .o
+%_xdr.c: %.x
+       $(RPCGEN) $(ALL_RPCFLAGS) -c -o $(SYM_DIR)/$*_xdr.c $*.x
+
+%_svc.c: %.x
+       $(RPCGEN) $(ALL_RPCFLAGS) -m -o $(SYM_DIR)/$*_svc.c $*.x
+
+after_install:
+       $(RM) -rf $(INSTALLED_PRODUCTS)
diff --git a/bootparams/bootparams/Makefile.preamble b/bootparams/bootparams/Makefile.preamble
new file mode 100644 (file)
index 0000000..9253661
--- /dev/null
@@ -0,0 +1,144 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+AFTER_INSTALL = after_install
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+LIBRARY_STYLE = STATIC
+
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+OTHER_GARBAGE = *~
+OTHER_PROJECT_HEADERS = bootparam_prot.h
+OTHER_OFILES = bootparam_prot_xdr.o bootparam_prot_svc.o
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+# DSTROOT = $(HOME)
+-include ../../Makefile.include
diff --git a/bootparams/bootparams/PB.project b/bootparams/bootparams/PB.project
new file mode 100644 (file)
index 0000000..d753020
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    CURRENTLY_ACTIVE_VERSION = YES; 
+    DEPLOY_WITH_VERSION_NAME = A; 
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, bootparam_prot.x); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/local/lib; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_INSTALLDIR = /lib; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PDO_UNIX_PUBLICHEADERSDIR = "$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)"; 
+    PROJECTNAME = bootparams; 
+    PROJECTTYPE = Library; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = /Developer/Libraries; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+    WINDOWS_PUBLICHEADERSDIR = "$(HOMEDRIVE)$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)"; 
+}
diff --git a/bootparams/bootparams/bootparam_prot.x b/bootparams/bootparams/bootparam_prot.x
new file mode 100644 (file)
index 0000000..0339a81
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* @(#)bootparam_prot.x        2.1 88/08/01 4.0 RPCSRC */
+/* @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+/*
+ * RPC for bootparms service.
+ * There are two procedures:
+ *   WHOAMI takes a net address and returns a client name and also a
+ *     likely net address for routing
+ *   GETFILE takes a client name and file identifier and returns the
+ *     server name, server net address and pathname for the file.
+ *   file identifiers typically include root, swap, pub and dump
+ */
+
+#ifdef RPC_HDR
+%#include <rpc/types.h>
+%#include <sys/time.h>
+%#include <sys/errno.h>
+#endif
+
+const MAX_MACHINE_NAME  = 255;
+const MAX_PATH_LEN     = 1024;
+const MAX_FILEID       = 32;
+const IP_ADDR_TYPE     = 1;
+
+typedef        string  bp_machine_name_t<MAX_MACHINE_NAME>;
+typedef        string  bp_path_t<MAX_PATH_LEN>;
+typedef        string  bp_fileid_t<MAX_FILEID>;
+
+struct ip_addr_t {
+       char    net;
+       char    host;
+       char    lh;
+       char    impno;
+};
+
+union bp_address switch (int address_type) {
+       case IP_ADDR_TYPE:
+               ip_addr_t       ip_addr;
+};
+
+struct bp_whoami_arg {
+       bp_address              client_address;
+};
+
+struct bp_whoami_res {
+       bp_machine_name_t       client_name;
+       bp_machine_name_t       domain_name;
+       bp_address              router_address;
+};
+
+struct bp_getfile_arg {
+       bp_machine_name_t       client_name;
+       bp_fileid_t             file_id;
+};
+       
+struct bp_getfile_res {
+       bp_machine_name_t       server_name;
+       bp_address              server_address;
+       bp_path_t               server_path;
+};
+
+program BOOTPARAMPROG {
+       version BOOTPARAMVERS {
+               bp_whoami_res   BOOTPARAMPROC_WHOAMI(bp_whoami_arg) = 1;
+               bp_getfile_res  BOOTPARAMPROC_GETFILE(bp_getfile_arg) = 2;
+       } = 1;
+} = 100026;
diff --git a/bootparams/bpwhoami.tproj/Makefile b/bootparams/bpwhoami.tproj/Makefile
new file mode 100644 (file)
index 0000000..1cf44ad
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = bpwhoami
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = bpwhoami.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/bootparams/bpwhoami.tproj/Makefile.postamble b/bootparams/bpwhoami.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..411cde6
--- /dev/null
@@ -0,0 +1,100 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/bootparams/bpwhoami.tproj/Makefile.preamble b/bootparams/bpwhoami.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..5a48598
--- /dev/null
@@ -0,0 +1,139 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+OTHER_GARBAGE = *~
+OTHER_LIBS = -lbootparams
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+# DSTROOT = $(HOME)
diff --git a/bootparams/bpwhoami.tproj/PB.project b/bootparams/bpwhoami.tproj/PB.project
new file mode 100644 (file)
index 0000000..516c248
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (bpwhoami.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_INSTALLDIR = /bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = bpwhoami; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = /Library/Executables; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/bootparams/bpwhoami.tproj/bpwhoami.c b/bootparams/bpwhoami.tproj/bpwhoami.c
new file mode 100644 (file)
index 0000000..c846417
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* 
+ * Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved
+ *
+ * bpwhoami.c
+ * - do a bootparams whoami call and echo the results to stdout
+ *
+ * The output is of the form:
+ * host_name=<hostname>
+ * nis_domain=<nis domain name>
+ * router=<router ip address>
+ * server_name=<server host name>
+ * server_ip_address=<server ip address>
+ *
+ * The program will exit with the following codes:
+ * 0   Successfully retrieved info
+ * 1   RPC timed out while attempting to retrieve info
+ * 2   Unrecoverable error ie. don't bother trying to call again
+ *
+ * Modification History:
+ * Aug  5, 1997                Dieter Siegund (dieter@apple.com)
+ * - lifted code from the old hostname -AUTOMATIC- source
+ */
+
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void usage __P((void));
+
+#include <netdb.h>
+#include <signal.h>
+#include <mach/boolean.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl_compat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <net/if.h>
+#include <rpc/rpc.h>
+#include <arpa/inet.h>
+#include "bootparam_prot.h"
+
+struct in_addr         ip_address;
+struct in_addr         net_mask;
+
+static __inline__
+u_long iptohl(struct in_addr ip)
+{
+    return (ntohl(ip.s_addr));
+}
+
+static __inline__ boolean_t
+in_subnet(struct in_addr netaddr, struct in_addr netmask, struct in_addr ip)
+{
+    if ((iptohl(ip) & iptohl(netmask)) 
+       != (iptohl(netaddr) & iptohl(netmask))) {
+       return (FALSE);
+    }
+    return (TRUE);
+}
+
+bool_t
+each_whoresult(result, from)
+     bp_whoami_res             *result;
+     struct sockaddr_in        *from;
+{
+       if (result) {
+           struct hostent *    host;
+           struct in_addr *    router;
+
+           /*
+            * guard against bogus router replies by making sure
+            * that the default router is on the same subnet
+            */
+           router = (struct in_addr *)
+               &result->router_address.bp_address_u.ip_addr;
+           if (in_subnet(*router, net_mask, ip_address)) {
+               if (result->client_name && result->client_name[0])
+                   printf("host_name=%s\n", result->client_name); 
+               if (result->domain_name && result->domain_name[0])
+                   printf("nis_domain=%s\n", result->domain_name);
+               printf("router=%s\n", inet_ntoa(*router));
+               host = gethostbyaddr((char *) &from->sin_addr,
+                                    sizeof (from->sin_addr), AF_INET);
+               if (host) {
+                   printf("server_name=%s\n", host->h_name);
+               }
+               printf("server_ip_address=%s\n", inet_ntoa(from->sin_addr));
+               return(TRUE);
+           }
+       }
+       return(FALSE);
+}
+
+#define MAX_IF         16
+
+static boolean_t
+getFirstInterface(struct ifreq * ret_p)
+{
+    struct ifconf      ifconf; /* points to ifreq */
+    struct ifreq  *    ifreq = NULL;
+    struct ifreq *     ifrp;
+    int                        size = sizeof(struct ifreq) * MAX_IF;
+    int                        sockfd;
+
+    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+       fprintf(stderr, "bpwhoami: socket call failed\n");
+       return (FALSE);
+    }
+
+    while (1) {
+       if (ifreq != NULL)
+           ifreq = (struct ifreq *)realloc(ifreq, size);
+       else
+           ifreq = (struct ifreq *)malloc(size);
+
+       if (ifreq == NULL)
+           goto err;
+
+       ifconf.ifc_len = size;
+       ifconf.ifc_req = ifreq;
+       if (ioctl(sockfd, SIOCGIFCONF, (caddr_t)&ifconf) < 0
+           || ifconf.ifc_len <= 0) {
+           fprintf(stderr, "bpwhoami: ioctl SIOCGIFCONF failed\n");
+           goto err;
+       }
+       if ((ifconf.ifc_len + sizeof(struct ifreq)) < size)
+           break;
+       size *= 2;
+    }
+#define IFR_NEXT(ifr)  \
+    ((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \
+                      MAX(0, (int) (ifr)->ifr_addr.sa_len \
+                          - (int) sizeof((ifr)->ifr_addr))))
+    for (ifrp = (struct ifreq *) ifconf.ifc_buf;
+        (char *) ifrp < &ifconf.ifc_buf[ifconf.ifc_len];
+        ifrp = IFR_NEXT(ifrp)) {
+       if (ifrp->ifr_addr.sa_family == AF_INET) {
+           struct ifreq        ifr;
+
+           strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
+           if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
+               ;
+           else if ((ifr.ifr_flags & IFF_LOOPBACK)
+                    || !(ifr.ifr_flags & IFF_UP))
+               ;
+           else if (ioctl(sockfd, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) 
+               ;
+           else {
+               net_mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+               *ret_p = *ifrp;
+               close(sockfd);
+               if (ifreq)
+                   free(ifreq);
+               return (TRUE);
+           }
+       }
+    }
+  err:
+    close(sockfd);
+    if (ifreq)
+       free(ifreq);
+    return (FALSE);
+}
+
+/*
+ * Routine: bp_whoami
+ * Function:
+ *     Do a BOOTPARAMS WHOAMI RPC to find out hostname, domain,
+ *     bootparams server, default router.
+ */
+int
+bp_whoami()
+{
+       extern enum clnt_stat   clnt_broadcast();
+       struct ifreq            ifr;
+       struct sockaddr_in      *sockin;
+       enum clnt_stat          stat;
+       struct bp_whoami_arg    who_arg;
+       struct bp_whoami_res    who_res;
+
+       if (getFirstInterface(&ifr) == FALSE)
+           return (2);
+
+       sockin = (struct sockaddr_in *) &ifr.ifr_addr;
+       ip_address = sockin->sin_addr;
+       who_arg.client_address.bp_address_u.ip_addr =
+           *((ip_addr_t *)&sockin->sin_addr);
+       who_arg.client_address.address_type = IP_ADDR_TYPE;
+       bzero(&who_res, sizeof (who_res));
+
+       /*
+        * Broadcast the whoami.
+        */
+       stat = clnt_broadcast(BOOTPARAMPROG, BOOTPARAMVERS,
+                             BOOTPARAMPROC_WHOAMI, xdr_bp_whoami_arg,
+                             &who_arg, xdr_bp_whoami_res, &who_res,
+                             each_whoresult);
+
+       if (stat == RPC_SUCCESS) {
+           return (0);
+       }
+       if (stat == RPC_TIMEDOUT)
+           return (1);
+       fprintf(stderr, "bpwhoami: ");
+       clnt_perrno(stat);
+       return (2);
+}
+
+int
+main(argc,argv)
+     int argc;
+     char *argv[];
+{
+    exit(bp_whoami());
+}
diff --git a/domainname.tproj/Makefile b/domainname.tproj/Makefile
new file mode 100644 (file)
index 0000000..12a1e35
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = domainname
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = domainname.c
+
+OTHERSRCS = Makefile.dist domainname.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /bin
+WINDOWS_INSTALLDIR = /bin
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/domainname.tproj/Makefile.dist b/domainname.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..755ae0d
--- /dev/null
@@ -0,0 +1,6 @@
+#      from: @(#)Makefile      5.3 (Berkeley) 5/11/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:57:38 wsanchez Exp $
+
+PROG=  domainname
+
+.include <bsd.prog.mk>
diff --git a/domainname.tproj/PB.project b/domainname.tproj/PB.project
new file mode 100644 (file)
index 0000000..b16d0b9
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (domainname.c); 
+        OTHER_SOURCES = (Makefile.dist, domainname.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = domainname; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/domainname.tproj/domainname.1 b/domainname.tproj/domainname.1
new file mode 100644 (file)
index 0000000..074bf43
--- /dev/null
@@ -0,0 +1,60 @@
+.\" Copyright (c) 1983, 1988, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    from: @(#)domainname.1  6.8 (Berkeley) 7/27/91
+.\"    $Id: domainname.1,v 1.1.1.1 1999/05/02 03:57:38 wsanchez Exp $
+.\"
+.Dd July 27, 1991
+.Dt DOMAINNAME 1
+.Os BSD 4.2
+.Sh NAME
+.Nm domainname
+.Nd set or print the name of the current domain
+.Sh SYNOPSIS
+.Nm domainname
+.Op Ar name-of-domain
+.Sh DESCRIPTION
+.Nm Domainname
+prints the domain name of the current host.  The super-user can
+set the domain name by supplying an argument; this is usually done in the
+network initialization script
+.Pa /etc/netstart ,
+normally run at boot
+time.
+.Sh SEE ALSO
+.Xr hostname 1 ,
+.Xr getdomainname 2 ,
+.Xr setdomainname 2 
+.Sh HISTORY
+The
+.Nm domainname
+command appeared in
+.Bx 4.2 .
diff --git a/domainname.tproj/domainname.c b/domainname.tproj/domainname.c
new file mode 100644 (file)
index 0000000..a229731
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: domainname.c,v 1.1.1.1 1999/05/02 03:57:38 wsanchez Exp $";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+
+static void usage __P((void));
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       char dom[MAXHOSTNAMELEN];
+
+       if( argc>2 ) {
+               usage ();
+               /* NOTREACHED */
+       }
+
+       if( argc==2 ) {
+               if( setdomainname(argv[1], strlen(argv[1])+1) == -1) {
+                       perror("setdomainname");
+                       exit(1);
+               }
+       } else {
+               if( getdomainname(dom, sizeof(dom)) == -1) {
+                       perror("getdomainname");
+                       exit(1);
+               }
+               printf("%s\n", dom);
+       }
+
+       exit(0);
+}
+
+static void
+usage ()
+{
+       (void)fprintf(stderr, "usage: domainname [name-of-domain]\n");
+       exit(1);
+}
diff --git a/ftp.tproj/Makefile b/ftp.tproj/Makefile
new file mode 100644 (file)
index 0000000..980a8c2
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ftp
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h ftp_var.h pathnames.h
+
+CFILES = cmds.c cmdtab.c domacro.c ftp.c ftp_var.c main.c\
+         ruserpass.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
+            h.template ftp.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ftp.tproj/Makefile.postamble b/ftp.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7823726
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/ftp.tproj/Makefile.preamble b/ftp.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/ftp.tproj/PB.project b/ftp.tproj/PB.project
new file mode 100644 (file)
index 0000000..3b40ec2
--- /dev/null
@@ -0,0 +1,34 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (extern.h, ftp_var.h, pathnames.h); 
+        OTHER_LINKED = (cmds.c, cmdtab.c, domacro.c, ftp.c, ftp_var.c, main.c, ruserpass.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            m.template, 
+            h.template, 
+            ftp.1
+        ); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ftp; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ftp.tproj/cmds.c b/ftp.tproj/cmds.c
new file mode 100644 (file)
index 0000000..6dd3f48
--- /dev/null
@@ -0,0 +1,2236 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * FTP User Program -- Command Routines.
+ */
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/ftp.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <glob.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "ftp_var.h"
+#include "pathnames.h"
+
+jmp_buf        jabort;
+char   *mname;
+char   *home = "/";
+
+/*
+ * `Another' gets another argument, and stores the new argc and argv.
+ * It reverts to the top level (via main.c's intr()) on EOF/error.
+ *
+ * Returns false if no new arguments have been added.
+ */
+int
+another(pargc, pargv, prompt)
+       int *pargc;
+       char ***pargv;
+       char *prompt;
+{
+       int len = strlen(line), ret;
+
+       if (len >= sizeof(line) - 3) {
+               printf("sorry, arguments too long\n");
+               intr();
+       }
+       printf("(%s) ", prompt);
+       line[len++] = ' ';
+       if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
+               intr();
+       len += strlen(&line[len]);
+       if (len > 0 && line[len - 1] == '\n')
+               line[len - 1] = '\0';
+       makeargv();
+       ret = margc > *pargc;
+       *pargc = margc;
+       *pargv = margv;
+       return (ret);
+}
+
+/*
+ * Connect to peer server and
+ * auto-login, if possible.
+ */
+void
+setpeer(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char *host;
+       short port;
+
+       if (connected) {
+               printf("Already connected to %s, use close first.\n",
+                       hostname);
+               code = -1;
+               return;
+       }
+       if (argc < 2)
+               (void) another(&argc, &argv, "to");
+       if (argc < 2 || argc > 3) {
+               printf("usage: %s host-name [port]\n", argv[0]);
+               code = -1;
+               return;
+       }
+       port = sp->s_port;
+       if (argc > 2) {
+               port = atoi(argv[2]);
+               if (port <= 0) {
+                       printf("%s: bad port number-- %s\n", argv[1], argv[2]);
+                       printf ("usage: %s host-name [port]\n", argv[0]);
+                       code = -1;
+                       return;
+               }
+               port = htons(port);
+       }
+       host = hookup(argv[1], port);
+       if (host) {
+               int overbose;
+
+               connected = 1;
+               /*
+                * Set up defaults for FTP.
+                */
+               (void) strcpy(typename, "ascii"), type = TYPE_A;
+               curtype = TYPE_A;
+               (void) strcpy(formname, "non-print"), form = FORM_N;
+               (void) strcpy(modename, "stream"), mode = MODE_S;
+               (void) strcpy(structname, "file"), stru = STRU_F;
+               (void) strcpy(bytename, "8"), bytesize = 8;
+               if (autologin)
+                       (void) login(argv[1]);
+
+#if (defined(unix) || defined(__APPLE__)) && NBBY == 8
+/*
+ * this ifdef is to keep someone form "porting" this to an incompatible
+ * system and not checking this out. This way they have to think about it.
+ */
+               overbose = verbose;
+               if (debug == 0)
+                       verbose = -1;
+               if (command("SYST") == COMPLETE && overbose) {
+                       char *cp, c;
+                       cp = strchr(reply_string+4, ' ');
+                       if (cp == NULL)
+                               cp = strchr(reply_string+4, '\r');
+                       if (cp) {
+                               if (cp[-1] == '.')
+                                       cp--;
+                               c = *cp;
+                               *cp = '\0';
+                       }
+
+                       printf("Remote system type is %s.\n",
+                               reply_string+4);
+                       if (cp)
+                               *cp = c;
+               }
+               if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
+                       if (proxy)
+                               unix_proxy = 1;
+                       else
+                               unix_server = 1;
+                       /*
+                        * Set type to 0 (not specified by user),
+                        * meaning binary by default, but don't bother
+                        * telling server.  We can use binary
+                        * for text files unless changed by the user.
+                        */
+                       type = 0;
+                       (void) strcpy(typename, "binary");
+                       if (overbose)
+                           printf("Using %s mode to transfer files.\n",
+                               typename);
+               } else {
+                       if (proxy)
+                               unix_proxy = 0;
+                       else
+                               unix_server = 0;
+                       if (overbose && 
+                           !strncmp(reply_string, "215 TOPS20", 10))
+                               printf(
+"Remember to set tenex mode when transfering binary files from this machine.\n");
+               }
+               verbose = overbose;
+#endif /* unix */
+       }
+}
+
+struct types {
+       char    *t_name;
+       char    *t_mode;
+       int     t_type;
+       char    *t_arg;
+} types[] = {
+       { "ascii",      "A",    TYPE_A, 0 },
+       { "binary",     "I",    TYPE_I, 0 },
+       { "image",      "I",    TYPE_I, 0 },
+       { "ebcdic",     "E",    TYPE_E, 0 },
+       { "tenex",      "L",    TYPE_L, bytename },
+       { NULL }
+};
+
+/*
+ * Set transfer type.
+ */
+void
+settype(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct types *p;
+       int comret;
+
+       if (argc > 2) {
+               char *sep;
+
+               printf("usage: %s [", argv[0]);
+               sep = " ";
+               for (p = types; p->t_name; p++) {
+                       printf("%s%s", sep, p->t_name);
+                       sep = " | ";
+               }
+               printf(" ]\n");
+               code = -1;
+               return;
+       }
+       if (argc < 2) {
+               printf("Using %s mode to transfer files.\n", typename);
+               code = 0;
+               return;
+       }
+       for (p = types; p->t_name; p++)
+               if (strcmp(argv[1], p->t_name) == 0)
+                       break;
+       if (p->t_name == 0) {
+               printf("%s: unknown mode\n", argv[1]);
+               code = -1;
+               return;
+       }
+       if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
+               comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
+       else
+               comret = command("TYPE %s", p->t_mode);
+       if (comret == COMPLETE) {
+               (void) strcpy(typename, p->t_name);
+               curtype = type = p->t_type;
+       }
+}
+
+/*
+ * Internal form of settype; changes current type in use with server
+ * without changing our notion of the type for data transfers.
+ * Used to change to and from ascii for listings.
+ */
+void
+changetype(newtype, show)
+       int newtype, show;
+{
+       struct types *p;
+       int comret, oldverbose = verbose;
+
+       if (newtype == 0)
+               newtype = TYPE_I;
+       if (newtype == curtype)
+               return;
+       if (debug == 0 && show == 0)
+               verbose = 0;
+       for (p = types; p->t_name; p++)
+               if (newtype == p->t_type)
+                       break;
+       if (p->t_name == 0) {
+               printf("ftp: internal error: unknown type %d\n", newtype);
+               return;
+       }
+       if (newtype == TYPE_L && bytename[0] != '\0')
+               comret = command("TYPE %s %s", p->t_mode, bytename);
+       else
+               comret = command("TYPE %s", p->t_mode);
+       if (comret == COMPLETE)
+               curtype = newtype;
+       verbose = oldverbose;
+}
+
+char *stype[] = {
+       "type",
+       "",
+       0
+};
+
+/*
+ * Set binary transfer type.
+ */
+/*VARARGS*/
+void
+setbinary(argc, argv)
+       int argc;
+       char **argv;
+{
+
+       stype[1] = "binary";
+       settype(2, stype);
+}
+
+/*
+ * Set ascii transfer type.
+ */
+/*VARARGS*/
+void
+setascii(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       stype[1] = "ascii";
+       settype(2, stype);
+}
+
+/*
+ * Set tenex transfer type.
+ */
+/*VARARGS*/
+void
+settenex(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       stype[1] = "tenex";
+       settype(2, stype);
+}
+
+/*
+ * Set file transfer mode.
+ */
+/*ARGSUSED*/
+void
+setftmode(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       printf("We only support %s mode, sorry.\n", modename);
+       code = -1;
+}
+
+/*
+ * Set file transfer format.
+ */
+/*ARGSUSED*/
+void
+setform(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       printf("We only support %s format, sorry.\n", formname);
+       code = -1;
+}
+
+/*
+ * Set file transfer structure.
+ */
+/*ARGSUSED*/
+void
+setstruct(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       printf("We only support %s structure, sorry.\n", structname);
+       code = -1;
+}
+
+/*
+ * Send a single file.
+ */
+void
+put(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char *cmd;
+       int loc = 0;
+       char *oldargv1, *oldargv2;
+
+       if (argc == 2) {
+               argc++;
+               argv[2] = argv[1];
+               loc++;
+       }
+       if (argc < 2 && !another(&argc, &argv, "local-file"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "remote-file")) {
+usage:
+               printf("usage: %s local-file remote-file\n", argv[0]);
+               code = -1;
+               return;
+       }
+       oldargv1 = argv[1];
+       oldargv2 = argv[2];
+       if (!globulize(&argv[1])) {
+               code = -1;
+               return;
+       }
+       /*
+        * If "globulize" modifies argv[1], and argv[2] is a copy of
+        * the old argv[1], make it a copy of the new argv[1].
+        */
+       if (argv[1] != oldargv1 && argv[2] == oldargv1) {
+               argv[2] = argv[1];
+       }
+       cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
+       if (loc && ntflag) {
+               argv[2] = dotrans(argv[2]);
+       }
+       if (loc && mapflag) {
+               argv[2] = domap(argv[2]);
+       }
+       sendrequest(cmd, argv[1], argv[2],
+           argv[1] != oldargv1 || argv[2] != oldargv2);
+}
+
+/*
+ * Send multiple files.
+ */
+void
+mput(argc, argv)
+       int argc;
+       char **argv;
+{
+       int i;
+       sig_t oldintr;
+       int ointer;
+       char *tp;
+
+       if (argc < 2 && !another(&argc, &argv, "local-files")) {
+               printf("usage: %s local-files\n", argv[0]);
+               code = -1;
+               return;
+       }
+       mname = argv[0];
+       mflag = 1;
+       oldintr = signal(SIGINT, mabort);
+       (void) setjmp(jabort);
+       if (proxy) {
+               char *cp, *tp2, tmpbuf[MAXPATHLEN];
+
+               while ((cp = remglob(argv,0)) != NULL) {
+                       if (*cp == 0) {
+                               mflag = 0;
+                               continue;
+                       }
+                       if (mflag && confirm(argv[0], cp)) {
+                               tp = cp;
+                               if (mcase) {
+                                       while (*tp && !islower(*tp)) {
+                                               tp++;
+                                       }
+                                       if (!*tp) {
+                                               tp = cp;
+                                               tp2 = tmpbuf;
+                                               while ((*tp2 = *tp) != NULL) {
+                                                    if (isupper(*tp2)) {
+                                                       *tp2 = 'a' + *tp2 - 'A';
+                                                    }
+                                                    tp++;
+                                                    tp2++;
+                                               }
+                                       }
+                                       tp = tmpbuf;
+                               }
+                               if (ntflag) {
+                                       tp = dotrans(tp);
+                               }
+                               if (mapflag) {
+                                       tp = domap(tp);
+                               }
+                               sendrequest((sunique) ? "STOU" : "STOR",
+                                   cp, tp, cp != tp || !interactive);
+                               if (!mflag && fromatty) {
+                                       ointer = interactive;
+                                       interactive = 1;
+                                       if (confirm("Continue with","mput")) {
+                                               mflag++;
+                                       }
+                                       interactive = ointer;
+                               }
+                       }
+               }
+               (void) signal(SIGINT, oldintr);
+               mflag = 0;
+               return;
+       }
+       for (i = 1; i < argc; i++) {
+               char **cpp, **gargs;
+               glob_t gl;
+               int flags;
+
+               if (!doglob) {
+                       if (mflag && confirm(argv[0], argv[i])) {
+                               tp = (ntflag) ? dotrans(argv[i]) : argv[i];
+                               tp = (mapflag) ? domap(tp) : tp;
+                               sendrequest((sunique) ? "STOU" : "STOR",
+                                   argv[i], tp, tp != argv[i] || !interactive);
+                               if (!mflag && fromatty) {
+                                       ointer = interactive;
+                                       interactive = 1;
+                                       if (confirm("Continue with","mput")) {
+                                               mflag++;
+                                       }
+                                       interactive = ointer;
+                               }
+                       }
+                       continue;
+               }
+
+               memset(&gl, 0, sizeof(gl));
+               flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+               if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
+                       warnx("%s: not found", argv[i]);
+                       globfree(&gl);
+                       continue;
+               }
+               for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
+                       if (mflag && confirm(argv[0], *cpp)) {
+                               tp = (ntflag) ? dotrans(*cpp) : *cpp;
+                               tp = (mapflag) ? domap(tp) : tp;
+                               sendrequest((sunique) ? "STOU" : "STOR",
+                                   *cpp, tp, *cpp != tp || !interactive);
+                               if (!mflag && fromatty) {
+                                       ointer = interactive;
+                                       interactive = 1;
+                                       if (confirm("Continue with","mput")) {
+                                               mflag++;
+                                       }
+                                       interactive = ointer;
+                               }
+                       }
+               }
+               globfree(&gl);
+       }
+       (void) signal(SIGINT, oldintr);
+       mflag = 0;
+}
+
+void
+reget(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       (void) getit(argc, argv, 1, "r+w");
+}
+
+void
+get(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
+}
+
+/*
+ * Receive one file.
+ */
+int
+getit(argc, argv, restartit, mode)
+       int argc;
+       char *argv[];
+       char *mode;
+       int restartit;
+{
+       int loc = 0;
+       char *oldargv1, *oldargv2;
+
+       if (argc == 2) {
+               argc++;
+               argv[2] = argv[1];
+               loc++;
+       }
+       if (argc < 2 && !another(&argc, &argv, "remote-file"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+               printf("usage: %s remote-file [ local-file ]\n", argv[0]);
+               code = -1;
+               return (0);
+       }
+       oldargv1 = argv[1];
+       oldargv2 = argv[2];
+       if (!globulize(&argv[2])) {
+               code = -1;
+               return (0);
+       }
+       if (loc && mcase) {
+               char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
+
+               while (*tp && !islower(*tp)) {
+                       tp++;
+               }
+               if (!*tp) {
+                       tp = argv[2];
+                       tp2 = tmpbuf;
+                       while ((*tp2 = *tp) != NULL) {
+                               if (isupper(*tp2)) {
+                                       *tp2 = 'a' + *tp2 - 'A';
+                               }
+                               tp++;
+                               tp2++;
+                       }
+                       argv[2] = tmpbuf;
+               }
+       }
+       if (loc && ntflag)
+               argv[2] = dotrans(argv[2]);
+       if (loc && mapflag)
+               argv[2] = domap(argv[2]);
+       if (restartit) {
+               struct stat stbuf;
+               int ret;
+
+               ret = stat(argv[2], &stbuf);
+               if (restartit == 1) {
+                       if (ret < 0) {
+                               warn("local: %s", argv[2]);
+                               return (0);
+                       }
+                       restart_point = stbuf.st_size;
+               } else {
+                       if (ret == 0) {
+                               int overbose;
+
+                               overbose = verbose;
+                               if (debug == 0)
+                                       verbose = -1;
+                               if (command("MDTM %s", argv[1]) == COMPLETE) {
+                                       int yy, mo, day, hour, min, sec;
+                                       struct tm *tm;
+                                       verbose = overbose;
+                                       sscanf(reply_string,
+                                           "%*s %04d%02d%02d%02d%02d%02d",
+                                           &yy, &mo, &day, &hour, &min, &sec);
+                                       tm = gmtime(&stbuf.st_mtime);
+                                       tm->tm_mon++;
+                                       if (tm->tm_year > yy%100)
+                                               return (1);
+                                       if ((tm->tm_year == yy%100 && 
+                                           tm->tm_mon > mo) ||
+                                          (tm->tm_mon == mo && 
+                                           tm->tm_mday > day) ||
+                                          (tm->tm_mday == day && 
+                                           tm->tm_hour > hour) ||
+                                          (tm->tm_hour == hour && 
+                                           tm->tm_min > min) ||
+                                          (tm->tm_min == min && 
+                                           tm->tm_sec > sec))
+                                               return (1);
+                               } else {
+                                       printf("%s\n", reply_string);
+                                       verbose = overbose;
+                                       return (0);
+                               }
+                       }
+               }
+       }
+
+       recvrequest("RETR", argv[2], argv[1], mode,
+           argv[1] != oldargv1 || argv[2] != oldargv2);
+       restart_point = 0;
+       return (0);
+}
+
+/* ARGSUSED */
+void
+mabort(signo)
+       int signo;
+{
+       int ointer;
+
+       printf("\n");
+       (void) fflush(stdout);
+       if (mflag && fromatty) {
+               ointer = interactive;
+               interactive = 1;
+               if (confirm("Continue with", mname)) {
+                       interactive = ointer;
+                       longjmp(jabort,0);
+               }
+               interactive = ointer;
+       }
+       mflag = 0;
+       longjmp(jabort,0);
+}
+
+/*
+ * Get multiple files.
+ */
+void
+mget(argc, argv)
+       int argc;
+       char **argv;
+{
+       sig_t oldintr;
+       int ch, ointer;
+       char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
+
+       if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+               printf("usage: %s remote-files\n", argv[0]);
+               code = -1;
+               return;
+       }
+       mname = argv[0];
+       mflag = 1;
+       oldintr = signal(SIGINT, mabort);
+       (void) setjmp(jabort);
+       while ((cp = remglob(argv,proxy)) != NULL) {
+               if (*cp == '\0') {
+                       mflag = 0;
+                       continue;
+               }
+               if (mflag && confirm(argv[0], cp)) {
+                       tp = cp;
+                       if (mcase) {
+                               for (tp2 = tmpbuf; ch = *tp++;)
+                                       *tp2++ = isupper(ch) ? tolower(ch) : ch;
+                               tp = tmpbuf;
+                       }
+                       if (ntflag) {
+                               tp = dotrans(tp);
+                       }
+                       if (mapflag) {
+                               tp = domap(tp);
+                       }
+                       recvrequest("RETR", tp, cp, "w",
+                           tp != cp || !interactive);
+                       if (!mflag && fromatty) {
+                               ointer = interactive;
+                               interactive = 1;
+                               if (confirm("Continue with","mget")) {
+                                       mflag++;
+                               }
+                               interactive = ointer;
+                       }
+               }
+       }
+       (void) signal(SIGINT,oldintr);
+       mflag = 0;
+}
+
+char *
+remglob(argv,doswitch)
+       char *argv[];
+       int doswitch;
+{
+       char temp[16];
+       static char buf[MAXPATHLEN];
+       static FILE *ftemp = NULL;
+       static char **args;
+       int oldverbose, oldhash;
+       char *cp, *mode;
+
+       if (!mflag) {
+               if (!doglob) {
+                       args = NULL;
+               }
+               else {
+                       if (ftemp) {
+                               (void) fclose(ftemp);
+                               ftemp = NULL;
+                       }
+               }
+               return (NULL);
+       }
+       if (!doglob) {
+               if (args == NULL)
+                       args = argv;
+               if ((cp = *++args) == NULL)
+                       args = NULL;
+               return (cp);
+       }
+       if (ftemp == NULL) {
+               (void) strcpy(temp, _PATH_TMP);
+               (void) mktemp(temp);
+               oldverbose = verbose, verbose = 0;
+               oldhash = hash, hash = 0;
+               if (doswitch) {
+                       pswitch(!proxy);
+               }
+               for (mode = "w"; *++argv != NULL; mode = "a")
+                       recvrequest ("NLST", temp, *argv, mode, 0);
+               if (doswitch) {
+                       pswitch(!proxy);
+               }
+               verbose = oldverbose; hash = oldhash;
+               ftemp = fopen(temp, "r");
+               (void) unlink(temp);
+               if (ftemp == NULL) {
+                       printf("can't find list of remote files, oops\n");
+                       return (NULL);
+               }
+       }
+       if (fgets(buf, sizeof (buf), ftemp) == NULL) {
+               (void) fclose(ftemp), ftemp = NULL;
+               return (NULL);
+       }
+       if ((cp = strchr(buf, '\n')) != NULL)
+               *cp = '\0';
+       return (buf);
+}
+
+char *
+onoff(bool)
+       int bool;
+{
+
+       return (bool ? "on" : "off");
+}
+
+/*
+ * Show status.
+ */
+/*ARGSUSED*/
+void
+status(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int i;
+
+       if (connected)
+               printf("Connected to %s.\n", hostname);
+       else
+               printf("Not connected.\n");
+       if (!proxy) {
+               pswitch(1);
+               if (connected) {
+                       printf("Connected for proxy commands to %s.\n", hostname);
+               }
+               else {
+                       printf("No proxy connection.\n");
+               }
+               pswitch(0);
+       }
+       printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
+               modename, typename, formname, structname);
+       printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 
+               onoff(verbose), onoff(bell), onoff(interactive),
+               onoff(doglob));
+       printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
+               onoff(runique));
+       printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
+       if (ntflag) {
+               printf("Ntrans: (in) %s (out) %s\n", ntin,ntout);
+       }
+       else {
+               printf("Ntrans: off\n");
+       }
+       if (mapflag) {
+               printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
+       }
+       else {
+               printf("Nmap: off\n");
+       }
+       printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
+               onoff(hash), onoff(sendport));
+       if (macnum > 0) {
+               printf("Macros:\n");
+               for (i=0; i<macnum; i++) {
+                       printf("\t%s\n",macros[i].mac_name);
+               }
+       }
+       code = 0;
+}
+
+/*
+ * Set beep on cmd completed mode.
+ */
+/*VARARGS*/
+void
+setbell(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       bell = !bell;
+       printf("Bell mode %s.\n", onoff(bell));
+       code = bell;
+}
+
+/*
+ * Turn on packet tracing.
+ */
+/*VARARGS*/
+void
+settrace(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       trace = !trace;
+       printf("Packet tracing %s.\n", onoff(trace));
+       code = trace;
+}
+
+/*
+ * Toggle hash mark printing during transfers.
+ */
+/*VARARGS*/
+void
+sethash(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       hash = !hash;
+       printf("Hash mark printing %s", onoff(hash));
+       code = hash;
+       if (hash)
+               printf(" (%d bytes/hash mark)", 1024);
+       printf(".\n");
+}
+
+/*
+ * Turn on printing of server echo's.
+ */
+/*VARARGS*/
+void
+setverbose(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       verbose = !verbose;
+       printf("Verbose mode %s.\n", onoff(verbose));
+       code = verbose;
+}
+
+/*
+ * Toggle PORT cmd use before each data connection.
+ */
+/*VARARGS*/
+void
+setport(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       sendport = !sendport;
+       printf("Use of PORT cmds %s.\n", onoff(sendport));
+       code = sendport;
+}
+
+/*
+ * Turn on interactive prompting
+ * during mget, mput, and mdelete.
+ */
+/*VARARGS*/
+void
+setprompt(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       interactive = !interactive;
+       printf("Interactive mode %s.\n", onoff(interactive));
+       code = interactive;
+}
+
+/*
+ * Toggle metacharacter interpretation
+ * on local file names.
+ */
+/*VARARGS*/
+void
+setglob(argc, argv)
+       int argc;
+       char *argv[];
+{
+       
+       doglob = !doglob;
+       printf("Globbing %s.\n", onoff(doglob));
+       code = doglob;
+}
+
+/*
+ * Set debugging mode on/off and/or
+ * set level of debugging.
+ */
+/*VARARGS*/
+void
+setdebug(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int val;
+
+       if (argc > 1) {
+               val = atoi(argv[1]);
+               if (val < 0) {
+                       printf("%s: bad debugging value.\n", argv[1]);
+                       code = -1;
+                       return;
+               }
+       } else
+               val = !debug;
+       debug = val;
+       if (debug)
+               options |= SO_DEBUG;
+       else
+               options &= ~SO_DEBUG;
+       printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
+       code = debug > 0;
+}
+
+/*
+ * Set current working directory
+ * on remote machine.
+ */
+void
+cd(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "remote-directory")) {
+               printf("usage: %s remote-directory\n", argv[0]);
+               code = -1;
+               return;
+       }
+       if (command("CWD %s", argv[1]) == ERROR && code == 500) {
+               if (verbose)
+                       printf("CWD command not recognized, trying XCWD\n");
+               (void) command("XCWD %s", argv[1]);
+       }
+}
+
+/*
+ * Set current working directory
+ * on local machine.
+ */
+void
+lcd(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char buf[MAXPATHLEN];
+
+       if (argc < 2)
+               argc++, argv[1] = home;
+       if (argc != 2) {
+               printf("usage: %s local-directory\n", argv[0]);
+               code = -1;
+               return;
+       }
+       if (!globulize(&argv[1])) {
+               code = -1;
+               return;
+       }
+       if (chdir(argv[1]) < 0) {
+               warn("local: %s", argv[1]);
+               code = -1;
+               return;
+       }
+       if (getwd(buf) != NULL)
+               printf("Local directory now %s\n", buf);
+       else
+               warnx("getwd: %s", buf);
+       code = 0;
+}
+
+/*
+ * Delete a single file.
+ */
+void
+delete(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "remote-file")) {
+               printf("usage: %s remote-file\n", argv[0]);
+               code = -1;
+               return;
+       }
+       (void) command("DELE %s", argv[1]);
+}
+
+/*
+ * Delete multiple files.
+ */
+void
+mdelete(argc, argv)
+       int argc;
+       char **argv;
+{
+       sig_t oldintr;
+       int ointer;
+       char *cp;
+
+       if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+               printf("usage: %s remote-files\n", argv[0]);
+               code = -1;
+               return;
+       }
+       mname = argv[0];
+       mflag = 1;
+       oldintr = signal(SIGINT, mabort);
+       (void) setjmp(jabort);
+       while ((cp = remglob(argv,0)) != NULL) {
+               if (*cp == '\0') {
+                       mflag = 0;
+                       continue;
+               }
+               if (mflag && confirm(argv[0], cp)) {
+                       (void) command("DELE %s", cp);
+                       if (!mflag && fromatty) {
+                               ointer = interactive;
+                               interactive = 1;
+                               if (confirm("Continue with", "mdelete")) {
+                                       mflag++;
+                               }
+                               interactive = ointer;
+                       }
+               }
+       }
+       (void) signal(SIGINT, oldintr);
+       mflag = 0;
+}
+
+/*
+ * Rename a remote file.
+ */
+void
+renamefile(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "from-name"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "to-name")) {
+usage:
+               printf("%s from-name to-name\n", argv[0]);
+               code = -1;
+               return;
+       }
+       if (command("RNFR %s", argv[1]) == CONTINUE)
+               (void) command("RNTO %s", argv[2]);
+}
+
+/*
+ * Get a directory listing
+ * of remote files.
+ */
+void
+ls(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char *cmd;
+
+       if (argc < 2)
+               argc++, argv[1] = NULL;
+       if (argc < 3)
+               argc++, argv[2] = "-";
+       if (argc > 3) {
+               printf("usage: %s remote-directory local-file\n", argv[0]);
+               code = -1;
+               return;
+       }
+       cmd = argv[0][0] == 'n' ? "NLST" : "LIST";
+       if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
+               code = -1;
+               return;
+       }
+       if (strcmp(argv[2], "-") && *argv[2] != '|')
+               if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) {
+                       code = -1;
+                       return;
+       }
+       recvrequest(cmd, argv[2], argv[1], "w", 0);
+}
+
+/*
+ * Get a directory listing
+ * of multiple remote files.
+ */
+void
+mls(argc, argv)
+       int argc;
+       char **argv;
+{
+       sig_t oldintr;
+       int ointer, i;
+       char *cmd, mode[1], *dest;
+
+       if (argc < 2 && !another(&argc, &argv, "remote-files"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+               printf("usage: %s remote-files local-file\n", argv[0]);
+               code = -1;
+               return;
+       }
+       dest = argv[argc - 1];
+       argv[argc - 1] = NULL;
+       if (strcmp(dest, "-") && *dest != '|')
+               if (!globulize(&dest) ||
+                   !confirm("output to local-file:", dest)) {
+                       code = -1;
+                       return;
+       }
+       cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
+       mname = argv[0];
+       mflag = 1;
+       oldintr = signal(SIGINT, mabort);
+       (void) setjmp(jabort);
+       for (i = 1; mflag && i < argc-1; ++i) {
+               *mode = (i == 1) ? 'w' : 'a';
+               recvrequest(cmd, dest, argv[i], mode, 0);
+               if (!mflag && fromatty) {
+                       ointer = interactive;
+                       interactive = 1;
+                       if (confirm("Continue with", argv[0])) {
+                               mflag ++;
+                       }
+                       interactive = ointer;
+               }
+       }
+       (void) signal(SIGINT, oldintr);
+       mflag = 0;
+}
+
+/*
+ * Do a shell escape
+ */
+/*ARGSUSED*/
+void
+shell(argc, argv)
+       int argc;
+       char **argv;
+{
+       pid_t pid;
+       sig_t old1, old2;
+       char shellnam[40], *shell, *namep; 
+       union wait status;
+
+       old1 = signal (SIGINT, SIG_IGN);
+       old2 = signal (SIGQUIT, SIG_IGN);
+       if ((pid = fork()) == 0) {
+               for (pid = 3; pid < 20; pid++)
+                       (void) close(pid);
+               (void) signal(SIGINT, SIG_DFL);
+               (void) signal(SIGQUIT, SIG_DFL);
+               shell = getenv("SHELL");
+               if (shell == NULL)
+                       shell = _PATH_BSHELL;
+               namep = strrchr(shell,'/');
+               if (namep == NULL)
+                       namep = shell;
+               (void) strcpy(shellnam,"-");
+               (void) strcat(shellnam, ++namep);
+               if (strcmp(namep, "sh") != 0)
+                       shellnam[0] = '+';
+               if (debug) {
+                       printf ("%s\n", shell);
+                       (void) fflush (stdout);
+               }
+               if (argc > 1) {
+                       execl(shell,shellnam,"-c",altarg,(char *)0);
+               }
+               else {
+                       execl(shell,shellnam,(char *)0);
+               }
+               warn("%s", shell);
+               code = -1;
+               exit(1);
+       }
+       if (pid > 0)
+               while (wait((int *)&status) != pid)
+                       ;
+       (void) signal(SIGINT, old1);
+       (void) signal(SIGQUIT, old2);
+       if (pid == -1) {
+               warn("%s", "Try again later");
+               code = -1;
+       }
+       else {
+               code = 0;
+       }
+}
+
+/*
+ * Send new user information (re-login)
+ */
+void
+user(argc, argv)
+       int argc;
+       char **argv;
+{
+       char acct[80];
+       int n, aflag = 0;
+
+       if (argc < 2)
+               (void) another(&argc, &argv, "username");
+       if (argc < 2 || argc > 4) {
+               printf("usage: %s username [password] [account]\n", argv[0]);
+               code = -1;
+               return;
+       }
+       n = command("USER %s", argv[1]);
+       if (n == CONTINUE) {
+               if (argc < 3 )
+                       argv[2] = getpass("Password: "), argc++;
+               n = command("PASS %s", argv[2]);
+       }
+       if (n == CONTINUE) {
+               if (argc < 4) {
+                       printf("Account: "); (void) fflush(stdout);
+                       (void) fgets(acct, sizeof(acct) - 1, stdin);
+                       acct[strlen(acct) - 1] = '\0';
+                       argv[3] = acct; argc++;
+               }
+               n = command("ACCT %s", argv[3]);
+               aflag++;
+       }
+       if (n != COMPLETE) {
+               fprintf(stdout, "Login failed.\n");
+               return;
+       }
+       if (!aflag && argc == 4) {
+               (void) command("ACCT %s", argv[3]);
+       }
+}
+
+/*
+ * Print working directory.
+ */
+/*VARARGS*/
+void
+pwd(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int oldverbose = verbose;
+
+       /*
+        * If we aren't verbose, this doesn't do anything!
+        */
+       verbose = 1;
+       if (command("PWD") == ERROR && code == 500) {
+               printf("PWD command not recognized, trying XPWD\n");
+               (void) command("XPWD");
+       }
+       verbose = oldverbose;
+}
+
+/*
+ * Make a directory.
+ */
+void
+makedir(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+               printf("usage: %s directory-name\n", argv[0]);
+               code = -1;
+               return;
+       }
+       if (command("MKD %s", argv[1]) == ERROR && code == 500) {
+               if (verbose)
+                       printf("MKD command not recognized, trying XMKD\n");
+               (void) command("XMKD %s", argv[1]);
+       }
+}
+
+/*
+ * Remove a directory.
+ */
+void
+removedir(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+               printf("usage: %s directory-name\n", argv[0]);
+               code = -1;
+               return;
+       }
+       if (command("RMD %s", argv[1]) == ERROR && code == 500) {
+               if (verbose)
+                       printf("RMD command not recognized, trying XRMD\n");
+               (void) command("XRMD %s", argv[1]);
+       }
+}
+
+/*
+ * Send a line, verbatim, to the remote machine.
+ */
+void
+quote(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "command line to send")) {
+               printf("usage: %s line-to-send\n", argv[0]);
+               code = -1;
+               return;
+       }
+       quote1("", argc, argv);
+}
+
+/*
+ * Send a SITE command to the remote machine.  The line
+ * is sent verbatim to the remote machine, except that the
+ * word "SITE" is added at the front.
+ */
+void
+site(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
+               printf("usage: %s line-to-send\n", argv[0]);
+               code = -1;
+               return;
+       }
+       quote1("SITE ", argc, argv);
+}
+
+/*
+ * Turn argv[1..argc) into a space-separated string, then prepend initial text.
+ * Send the result as a one-line command and get response.
+ */
+void
+quote1(initial, argc, argv)
+       char *initial;
+       int argc;
+       char **argv;
+{
+       int i, len;
+       char buf[BUFSIZ];               /* must be >= sizeof(line) */
+
+       (void) strcpy(buf, initial);
+       if (argc > 1) {
+               len = strlen(buf);
+               len += strlen(strcpy(&buf[len], argv[1]));
+               for (i = 2; i < argc; i++) {
+                       buf[len++] = ' ';
+                       len += strlen(strcpy(&buf[len], argv[i]));
+               }
+       }
+       if (command(buf) == PRELIM) {
+               while (getreply(0) == PRELIM)
+                       continue;
+       }
+}
+
+void
+do_chmod(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "mode"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "file-name")) {
+usage:
+               printf("usage: %s mode file-name\n", argv[0]);
+               code = -1;
+               return;
+       }
+       (void) command("SITE CHMOD %s %s", argv[1], argv[2]);
+}
+
+void
+do_umask(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int oldverbose = verbose;
+
+       verbose = 1;
+       (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
+       verbose = oldverbose;
+}
+
+void
+idle(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int oldverbose = verbose;
+
+       verbose = 1;
+       (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
+       verbose = oldverbose;
+}
+
+/*
+ * Ask the other side for help.
+ */
+void
+rmthelp(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int oldverbose = verbose;
+
+       verbose = 1;
+       (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
+       verbose = oldverbose;
+}
+
+/*
+ * Terminate session and exit.
+ */
+/*VARARGS*/
+void
+quit(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (connected)
+               disconnect(0, 0);
+       pswitch(1);
+       if (connected) {
+               disconnect(0, 0);
+       }
+       exit(0);
+}
+
+/*
+ * Terminate session, but don't exit.
+ */
+void
+disconnect(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (!connected)
+               return;
+       (void) command("QUIT");
+       if (cout) {
+               (void) fclose(cout);
+       }
+       cout = NULL;
+       connected = 0;
+       data = -1;
+       if (!proxy) {
+               macnum = 0;
+       }
+}
+
+int
+confirm(cmd, file)
+       char *cmd, *file;
+{
+       char line[BUFSIZ];
+
+       if (!interactive)
+               return (1);
+       printf("%s %s? ", cmd, file);
+       (void) fflush(stdout);
+       if (fgets(line, sizeof line, stdin) == NULL)
+               return (0);
+       return (*line != 'n' && *line != 'N');
+}
+
+void
+fatal(msg)
+       char *msg;
+{
+
+       errx(1, "%s", msg);
+}
+
+/*
+ * Glob a local file name specification with
+ * the expectation of a single return value.
+ * Can't control multiple values being expanded
+ * from the expression, we return only the first.
+ */
+int
+globulize(cpp)
+       char **cpp;
+{
+       glob_t gl;
+       int flags;
+
+       if (!doglob)
+               return (1);
+
+       flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+       memset(&gl, 0, sizeof(gl));
+       if (glob(*cpp, flags, NULL, &gl) ||
+           gl.gl_pathc == 0) {
+               warnx("%s: not found", *cpp);
+               globfree(&gl);
+               return (0);
+       }
+       *cpp = strdup(gl.gl_pathv[0]);  /* XXX - wasted memory */
+       globfree(&gl);
+       return (1);
+}
+
+void
+account(argc,argv)
+       int argc;
+       char **argv;
+{
+       char acct[50], *ap;
+
+       if (argc > 1) {
+               ++argv;
+               --argc;
+               (void) strncpy(acct,*argv,49);
+               acct[49] = '\0';
+               while (argc > 1) {
+                       --argc;
+                       ++argv;
+                       (void) strncat(acct,*argv, 49-strlen(acct));
+               }
+               ap = acct;
+       }
+       else {
+               ap = getpass("Account:");
+       }
+       (void) command("ACCT %s", ap);
+}
+
+jmp_buf abortprox;
+
+void
+proxabort()
+{
+
+       if (!proxy) {
+               pswitch(1);
+       }
+       if (connected) {
+               proxflag = 1;
+       }
+       else {
+               proxflag = 0;
+       }
+       pswitch(0);
+       longjmp(abortprox,1);
+}
+
+void
+doproxy(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct cmd *c;
+       sig_t oldintr;
+
+       if (argc < 2 && !another(&argc, &argv, "command")) {
+               printf("usage: %s command\n", argv[0]);
+               code = -1;
+               return;
+       }
+       c = getcmd(argv[1]);
+       if (c == (struct cmd *) -1) {
+               printf("?Ambiguous command\n");
+               (void) fflush(stdout);
+               code = -1;
+               return;
+       }
+       if (c == 0) {
+               printf("?Invalid command\n");
+               (void) fflush(stdout);
+               code = -1;
+               return;
+       }
+       if (!c->c_proxy) {
+               printf("?Invalid proxy command\n");
+               (void) fflush(stdout);
+               code = -1;
+               return;
+       }
+       if (setjmp(abortprox)) {
+               code = -1;
+               return;
+       }
+       oldintr = signal(SIGINT, proxabort);
+       pswitch(1);
+       if (c->c_conn && !connected) {
+               printf("Not connected\n");
+               (void) fflush(stdout);
+               pswitch(0);
+               (void) signal(SIGINT, oldintr);
+               code = -1;
+               return;
+       }
+       (*c->c_handler)(argc-1, argv+1);
+       if (connected) {
+               proxflag = 1;
+       }
+       else {
+               proxflag = 0;
+       }
+       pswitch(0);
+       (void) signal(SIGINT, oldintr);
+}
+
+void
+setcase(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       mcase = !mcase;
+       printf("Case mapping %s.\n", onoff(mcase));
+       code = mcase;
+}
+
+void
+setcr(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       crflag = !crflag;
+       printf("Carriage Return stripping %s.\n", onoff(crflag));
+       code = crflag;
+}
+
+void
+setntrans(argc,argv)
+       int argc;
+       char *argv[];
+{
+       if (argc == 1) {
+               ntflag = 0;
+               printf("Ntrans off.\n");
+               code = ntflag;
+               return;
+       }
+       ntflag++;
+       code = ntflag;
+       (void) strncpy(ntin, argv[1], 16);
+       ntin[16] = '\0';
+       if (argc == 2) {
+               ntout[0] = '\0';
+               return;
+       }
+       (void) strncpy(ntout, argv[2], 16);
+       ntout[16] = '\0';
+}
+
+char *
+dotrans(name)
+       char *name;
+{
+       static char new[MAXPATHLEN];
+       char *cp1, *cp2 = new;
+       int i, ostop, found;
+
+       for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
+               continue;
+       for (cp1 = name; *cp1; cp1++) {
+               found = 0;
+               for (i = 0; *(ntin + i) && i < 16; i++) {
+                       if (*cp1 == *(ntin + i)) {
+                               found++;
+                               if (i < ostop) {
+                                       *cp2++ = *(ntout + i);
+                               }
+                               break;
+                       }
+               }
+               if (!found) {
+                       *cp2++ = *cp1;
+               }
+       }
+       *cp2 = '\0';
+       return (new);
+}
+
+void
+setnmap(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char *cp;
+
+       if (argc == 1) {
+               mapflag = 0;
+               printf("Nmap off.\n");
+               code = mapflag;
+               return;
+       }
+       if (argc < 3 && !another(&argc, &argv, "mapout")) {
+               printf("Usage: %s [mapin mapout]\n",argv[0]);
+               code = -1;
+               return;
+       }
+       mapflag = 1;
+       code = 1;
+       cp = strchr(altarg, ' ');
+       if (proxy) {
+               while(*++cp == ' ')
+                       continue;
+               altarg = cp;
+               cp = strchr(altarg, ' ');
+       }
+       *cp = '\0';
+       (void) strncpy(mapin, altarg, MAXPATHLEN - 1);
+       while (*++cp == ' ')
+               continue;
+       (void) strncpy(mapout, cp, MAXPATHLEN - 1);
+}
+
+char *
+domap(name)
+       char *name;
+{
+       static char new[MAXPATHLEN];
+       char *cp1 = name, *cp2 = mapin;
+       char *tp[9], *te[9];
+       int i, toks[9], toknum = 0, match = 1;
+
+       for (i=0; i < 9; ++i) {
+               toks[i] = 0;
+       }
+       while (match && *cp1 && *cp2) {
+               switch (*cp2) {
+                       case '\\':
+                               if (*++cp2 != *cp1) {
+                                       match = 0;
+                               }
+                               break;
+                       case '$':
+                               if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
+                                       if (*cp1 != *(++cp2+1)) {
+                                               toks[toknum = *cp2 - '1']++;
+                                               tp[toknum] = cp1;
+                                               while (*++cp1 && *(cp2+1)
+                                                       != *cp1);
+                                               te[toknum] = cp1;
+                                       }
+                                       cp2++;
+                                       break;
+                               }
+                               /* FALLTHROUGH */
+                       default:
+                               if (*cp2 != *cp1) {
+                                       match = 0;
+                               }
+                               break;
+               }
+               if (match && *cp1) {
+                       cp1++;
+               }
+               if (match && *cp2) {
+                       cp2++;
+               }
+       }
+       if (!match && *cp1) /* last token mismatch */
+       {
+               toks[toknum] = 0;
+       }
+       cp1 = new;
+       *cp1 = '\0';
+       cp2 = mapout;
+       while (*cp2) {
+               match = 0;
+               switch (*cp2) {
+                       case '\\':
+                               if (*(cp2 + 1)) {
+                                       *cp1++ = *++cp2;
+                               }
+                               break;
+                       case '[':
+LOOP:
+                               if (*++cp2 == '$' && isdigit(*(cp2+1))) { 
+                                       if (*++cp2 == '0') {
+                                               char *cp3 = name;
+
+                                               while (*cp3) {
+                                                       *cp1++ = *cp3++;
+                                               }
+                                               match = 1;
+                                       }
+                                       else if (toks[toknum = *cp2 - '1']) {
+                                               char *cp3 = tp[toknum];
+
+                                               while (cp3 != te[toknum]) {
+                                                       *cp1++ = *cp3++;
+                                               }
+                                               match = 1;
+                                       }
+                               }
+                               else {
+                                       while (*cp2 && *cp2 != ',' && 
+                                           *cp2 != ']') {
+                                               if (*cp2 == '\\') {
+                                                       cp2++;
+                                               }
+                                               else if (*cp2 == '$' &&
+                                                       isdigit(*(cp2+1))) {
+                                                       if (*++cp2 == '0') {
+                                                          char *cp3 = name;
+
+                                                          while (*cp3) {
+                                                               *cp1++ = *cp3++;
+                                                          }
+                                                       }
+                                                       else if (toks[toknum =
+                                                           *cp2 - '1']) {
+                                                          char *cp3=tp[toknum];
+
+                                                          while (cp3 !=
+                                                                 te[toknum]) {
+                                                               *cp1++ = *cp3++;
+                                                          }
+                                                       }
+                                               }
+                                               else if (*cp2) {
+                                                       *cp1++ = *cp2++;
+                                               }
+                                       }
+                                       if (!*cp2) {
+                                               printf("nmap: unbalanced brackets\n");
+                                               return (name);
+                                       }
+                                       match = 1;
+                                       cp2--;
+                               }
+                               if (match) {
+                                       while (*++cp2 && *cp2 != ']') {
+                                             if (*cp2 == '\\' && *(cp2 + 1)) {
+                                                       cp2++;
+                                             }
+                                       }
+                                       if (!*cp2) {
+                                               printf("nmap: unbalanced brackets\n");
+                                               return (name);
+                                       }
+                                       break;
+                               }
+                               switch (*++cp2) {
+                                       case ',':
+                                               goto LOOP;
+                                       case ']':
+                                               break;
+                                       default:
+                                               cp2--;
+                                               goto LOOP;
+                               }
+                               break;
+                       case '$':
+                               if (isdigit(*(cp2 + 1))) {
+                                       if (*++cp2 == '0') {
+                                               char *cp3 = name;
+
+                                               while (*cp3) {
+                                                       *cp1++ = *cp3++;
+                                               }
+                                       }
+                                       else if (toks[toknum = *cp2 - '1']) {
+                                               char *cp3 = tp[toknum];
+
+                                               while (cp3 != te[toknum]) {
+                                                       *cp1++ = *cp3++;
+                                               }
+                                       }
+                                       break;
+                               }
+                               /* intentional drop through */
+                       default:
+                               *cp1++ = *cp2;
+                               break;
+               }
+               cp2++;
+       }
+       *cp1 = '\0';
+       if (!*new) {
+               return (name);
+       }
+       return (new);
+}
+
+void
+setpassive(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       passivemode = !passivemode;
+       printf("Passive mode %s.\n", onoff(passivemode));
+       code = passivemode;
+}
+
+void
+setsunique(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       sunique = !sunique;
+       printf("Store unique %s.\n", onoff(sunique));
+       code = sunique;
+}
+
+void
+setrunique(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       runique = !runique;
+       printf("Receive unique %s.\n", onoff(runique));
+       code = runique;
+}
+
+/* change directory to perent directory */
+void
+cdup(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (command("CDUP") == ERROR && code == 500) {
+               if (verbose)
+                       printf("CDUP command not recognized, trying XCUP\n");
+               (void) command("XCUP");
+       }
+}
+
+/* restart transfer at specific point */
+void
+restart(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc != 2)
+               printf("restart: offset not specified\n");
+       else {
+               restart_point = atol(argv[1]);
+               printf("restarting at %qd. %s\n", restart_point,
+                   "execute get, put or append to initiate transfer");
+       }
+}
+
+/* show remote system type */
+void
+syst(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       (void) command("SYST");
+}
+
+void
+macdef(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char *tmp;
+       int c;
+
+       if (macnum == 16) {
+               printf("Limit of 16 macros have already been defined\n");
+               code = -1;
+               return;
+       }
+       if (argc < 2 && !another(&argc, &argv, "macro name")) {
+               printf("Usage: %s macro_name\n",argv[0]);
+               code = -1;
+               return;
+       }
+       if (interactive) {
+               printf("Enter macro line by line, terminating it with a null line\n");
+       }
+       (void) strncpy(macros[macnum].mac_name, argv[1], 8);
+       if (macnum == 0) {
+               macros[macnum].mac_start = macbuf;
+       }
+       else {
+               macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
+       }
+       tmp = macros[macnum].mac_start;
+       while (tmp != macbuf+4096) {
+               if ((c = getchar()) == EOF) {
+                       printf("macdef:end of file encountered\n");
+                       code = -1;
+                       return;
+               }
+               if ((*tmp = c) == '\n') {
+                       if (tmp == macros[macnum].mac_start) {
+                               macros[macnum++].mac_end = tmp;
+                               code = 0;
+                               return;
+                       }
+                       if (*(tmp-1) == '\0') {
+                               macros[macnum++].mac_end = tmp - 1;
+                               code = 0;
+                               return;
+                       }
+                       *tmp = '\0';
+               }
+               tmp++;
+       }
+       while (1) {
+               while ((c = getchar()) != '\n' && c != EOF)
+                       /* LOOP */;
+               if (c == EOF || getchar() == '\n') {
+                       printf("Macro not defined - 4k buffer exceeded\n");
+                       code = -1;
+                       return;
+               }
+       }
+}
+
+/*
+ * get size of file on remote machine
+ */
+void
+sizecmd(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "filename")) {
+               printf("usage: %s filename\n", argv[0]);
+               code = -1;
+               return;
+       }
+       (void) command("SIZE %s", argv[1]);
+}
+
+/*
+ * get last modification time of file on remote machine
+ */
+void
+modtime(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int overbose;
+
+       if (argc < 2 && !another(&argc, &argv, "filename")) {
+               printf("usage: %s filename\n", argv[0]);
+               code = -1;
+               return;
+       }
+       overbose = verbose;
+       if (debug == 0)
+               verbose = -1;
+       if (command("MDTM %s", argv[1]) == COMPLETE) {
+               int yy, mo, day, hour, min, sec;
+               sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
+                       &day, &hour, &min, &sec);
+               /* might want to print this in local time */
+               printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
+                       mo, day, yy, hour, min, sec);
+       } else
+               printf("%s\n", reply_string);
+       verbose = overbose;
+}
+
+/*
+ * show status on reomte machine
+ */
+void
+rmtstatus(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
+}
+
+/*
+ * get file if modtime is more recent than current file
+ */
+void
+newer(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (getit(argc, argv, -1, "w"))
+               printf("Local file \"%s\" is newer than remote file \"%s\"\n",
+                       argv[2], argv[1]);
+}
diff --git a/ftp.tproj/cmdtab.c b/ftp.tproj/cmdtab.c
new file mode 100644 (file)
index 0000000..177dd59
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include "ftp_var.h"
+
+/*
+ * User FTP -- Command Tables.
+ */
+
+char   accounthelp[] = "send account command to remote server";
+char   appendhelp[] =  "append to a file";
+char   asciihelp[] =   "set ascii transfer type";
+char   beephelp[] =    "beep when command completed";
+char   binaryhelp[] =  "set binary transfer type";
+char   casehelp[] =    "toggle mget upper/lower case id mapping";
+char   cdhelp[] =      "change remote working directory";
+char   cduphelp[] =    "change remote working directory to parent directory";
+char   chmodhelp[] =   "change file permissions of remote file";
+char   connecthelp[] = "connect to remote tftp";
+char   crhelp[] =      "toggle carriage return stripping on ascii gets";
+char   deletehelp[] =  "delete remote file";
+char   debughelp[] =   "toggle/set debugging mode";
+char   dirhelp[] =     "list contents of remote directory";
+char   disconhelp[] =  "terminate ftp session";
+char   domachelp[] =   "execute macro";
+char   formhelp[] =    "set file transfer format";
+char   globhelp[] =    "toggle metacharacter expansion of local file names";
+char   hashhelp[] =    "toggle printing `#' for each buffer transferred";
+char   helphelp[] =    "print local help information";
+char   idlehelp[] =    "get (set) idle timer on remote side";
+char   lcdhelp[] =     "change local working directory";
+char   lshelp[] =      "list contents of remote directory";
+char   macdefhelp[] =  "define a macro";
+char   mdeletehelp[] = "delete multiple files";
+char   mdirhelp[] =    "list contents of multiple remote directories";
+char   mgethelp[] =    "get multiple files";
+char   mkdirhelp[] =   "make directory on the remote machine";
+char   mlshelp[] =     "list contents of multiple remote directories";
+char   modtimehelp[] = "show last modification time of remote file";
+char   modehelp[] =    "set file transfer mode";
+char   mputhelp[] =    "send multiple files";
+char   newerhelp[] =   "get file if remote file is newer than local file ";
+char   nlisthelp[] =   "nlist contents of remote directory";
+char   nmaphelp[] =    "set templates for default file name mapping";
+char   ntranshelp[] =  "set translation table for default file name mapping";
+char   porthelp[] =    "toggle use of PORT cmd for each data connection";
+char   prompthelp[] =  "force interactive prompting on multiple commands";
+char   proxyhelp[] =   "issue command on alternate connection";
+char   pwdhelp[] =     "print working directory on remote machine";
+char   quithelp[] =    "terminate ftp session and exit";
+char   quotehelp[] =   "send arbitrary ftp command";
+char   receivehelp[] = "receive file";
+char   regethelp[] =   "get file restarting at end of local file";
+char   remotehelp[] =  "get help from remote server";
+char   renamehelp[] =  "rename file";
+char   restarthelp[]=  "restart file transfer at bytecount";
+char   rmdirhelp[] =   "remove directory on the remote machine";
+char   rmtstatushelp[]="show status of remote machine";
+char   runiquehelp[] = "toggle store unique for local files";
+char   resethelp[] =   "clear queued command replies";
+char   sendhelp[] =    "send one file";
+char   passivehelp[] = "enter passive transfer mode";
+char   sitehelp[] =    "send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information";
+char   shellhelp[] =   "escape to the shell";
+char   sizecmdhelp[] = "show size of remote file";
+char   statushelp[] =  "show current status";
+char   structhelp[] =  "set file transfer structure";
+char   suniquehelp[] = "toggle store unique on remote machine";
+char   systemhelp[] =  "show remote system type";
+char   tenexhelp[] =   "set tenex file transfer type";
+char   tracehelp[] =   "toggle packet tracing";
+char   typehelp[] =    "set file transfer type";
+char   umaskhelp[] =   "get (set) umask on remote side";
+char   userhelp[] =    "send new user information";
+char   verbosehelp[] = "toggle verbose mode";
+
+struct cmd cmdtab[] = {
+       { "!",          shellhelp,      0,      0,      0,      shell },
+       { "$",          domachelp,      1,      0,      0,      domacro },
+       { "account",    accounthelp,    0,      1,      1,      account},
+       { "append",     appendhelp,     1,      1,      1,      put },
+       { "ascii",      asciihelp,      0,      1,      1,      setascii },
+       { "bell",       beephelp,       0,      0,      0,      setbell },
+       { "binary",     binaryhelp,     0,      1,      1,      setbinary },
+       { "bye",        quithelp,       0,      0,      0,      quit },
+       { "case",       casehelp,       0,      0,      1,      setcase },
+       { "cd",         cdhelp,         0,      1,      1,      cd },
+       { "cdup",       cduphelp,       0,      1,      1,      cdup },
+       { "chmod",      chmodhelp,      0,      1,      1,      do_chmod },
+       { "close",      disconhelp,     0,      1,      1,      disconnect },
+       { "cr",         crhelp,         0,      0,      0,      setcr },
+       { "delete",     deletehelp,     0,      1,      1,      delete },
+       { "debug",      debughelp,      0,      0,      0,      setdebug },
+       { "dir",        dirhelp,        1,      1,      1,      ls },
+       { "disconnect", disconhelp,     0,      1,      1,      disconnect },
+       { "form",       formhelp,       0,      1,      1,      setform },
+       { "get",        receivehelp,    1,      1,      1,      get },
+       { "glob",       globhelp,       0,      0,      0,      setglob },
+       { "hash",       hashhelp,       0,      0,      0,      sethash },
+       { "help",       helphelp,       0,      0,      1,      help },
+       { "idle",       idlehelp,       0,      1,      1,      idle },
+       { "image",      binaryhelp,     0,      1,      1,      setbinary },
+       { "lcd",        lcdhelp,        0,      0,      0,      lcd },
+       { "ls",         lshelp,         1,      1,      1,      ls },
+       { "macdef",     macdefhelp,     0,      0,      0,      macdef },
+       { "mdelete",    mdeletehelp,    1,      1,      1,      mdelete },
+       { "mdir",       mdirhelp,       1,      1,      1,      mls },
+       { "mget",       mgethelp,       1,      1,      1,      mget },
+       { "mkdir",      mkdirhelp,      0,      1,      1,      makedir },
+       { "mls",        mlshelp,        1,      1,      1,      mls },
+       { "mode",       modehelp,       0,      1,      1,      setftmode },
+       { "modtime",    modtimehelp,    0,      1,      1,      modtime },
+       { "mput",       mputhelp,       1,      1,      1,      mput },
+       { "newer",      newerhelp,      1,      1,      1,      newer },
+       { "nmap",       nmaphelp,       0,      0,      1,      setnmap },
+       { "nlist",      nlisthelp,      1,      1,      1,      ls },
+       { "ntrans",     ntranshelp,     0,      0,      1,      setntrans },
+       { "open",       connecthelp,    0,      0,      1,      setpeer },
+       { "passive",    passivehelp,    0,      0,      0,      setpassive },
+       { "prompt",     prompthelp,     0,      0,      0,      setprompt },
+       { "proxy",      proxyhelp,      0,      0,      1,      doproxy },
+       { "sendport",   porthelp,       0,      0,      0,      setport },
+       { "put",        sendhelp,       1,      1,      1,      put },
+       { "pwd",        pwdhelp,        0,      1,      1,      pwd },
+       { "quit",       quithelp,       0,      0,      0,      quit },
+       { "quote",      quotehelp,      1,      1,      1,      quote },
+       { "recv",       receivehelp,    1,      1,      1,      get },
+       { "reget",      regethelp,      1,      1,      1,      reget },
+       { "rstatus",    rmtstatushelp,  0,      1,      1,      rmtstatus },
+       { "rhelp",      remotehelp,     0,      1,      1,      rmthelp },
+       { "rename",     renamehelp,     0,      1,      1,      renamefile },
+       { "reset",      resethelp,      0,      1,      1,      reset },
+       { "restart",    restarthelp,    1,      1,      1,      restart },
+       { "rmdir",      rmdirhelp,      0,      1,      1,      removedir },
+       { "runique",    runiquehelp,    0,      0,      1,      setrunique },
+       { "send",       sendhelp,       1,      1,      1,      put },
+       { "site",       sitehelp,       0,      1,      1,      site },
+       { "size",       sizecmdhelp,    1,      1,      1,      sizecmd },
+       { "status",     statushelp,     0,      0,      1,      status },
+       { "struct",     structhelp,     0,      1,      1,      setstruct },
+       { "system",     systemhelp,     0,      1,      1,      syst },
+       { "sunique",    suniquehelp,    0,      0,      1,      setsunique },
+       { "tenex",      tenexhelp,      0,      1,      1,      settenex },
+       { "trace",      tracehelp,      0,      0,      0,      settrace },
+       { "type",       typehelp,       0,      1,      1,      settype },
+       { "user",       userhelp,       0,      1,      1,      user },
+       { "umask",      umaskhelp,      0,      1,      1,      do_umask },
+       { "verbose",    verbosehelp,    0,      0,      0,      setverbose },
+       { "?",          helphelp,       0,      0,      1,      help },
+       { 0 },
+};
+
+int    NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1;
diff --git a/ftp.tproj/domacro.c b/ftp.tproj/domacro.c
new file mode 100644 (file)
index 0000000..19f0539
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+#include <strings.h>
+
+#include "ftp_var.h"
+
+void
+domacro(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int i, j, count = 2, loopflg = 0;
+       char *cp1, *cp2, line2[200];
+       struct cmd *c;
+
+       if (argc < 2 && !another(&argc, &argv, "macro name")) {
+               printf("Usage: %s macro_name.\n", argv[0]);
+               code = -1;
+               return;
+       }
+       for (i = 0; i < macnum; ++i) {
+               if (!strncmp(argv[1], macros[i].mac_name, 9)) {
+                       break;
+               }
+       }
+       if (i == macnum) {
+               printf("'%s' macro not found.\n", argv[1]);
+               code = -1;
+               return;
+       }
+       (void) strcpy(line2, line);
+TOP:
+       cp1 = macros[i].mac_start;
+       while (cp1 != macros[i].mac_end) {
+               while (isspace(*cp1)) {
+                       cp1++;
+               }
+               cp2 = line;
+               while (*cp1 != '\0') {
+                     switch(*cp1) {
+                           case '\\':
+                                *cp2++ = *++cp1;
+                                break;
+                           case '$':
+                                if (isdigit(*(cp1+1))) {
+                                   j = 0;
+                                   while (isdigit(*++cp1)) {
+                                         j = 10*j +  *cp1 - '0';
+                                   }
+                                   cp1--;
+                                   if (argc - 2 >= j) {
+                                       (void) strcpy(cp2, argv[j+1]);
+                                       cp2 += strlen(argv[j+1]);
+                                   }
+                                   break;
+                                }
+                                if (*(cp1+1) == 'i') {
+                                       loopflg = 1;
+                                       cp1++;
+                                       if (count < argc) {
+                                          (void) strcpy(cp2, argv[count]);
+                                          cp2 += strlen(argv[count]);
+                                       }
+                                       break;
+                               }
+                               /* intentional drop through */
+                           default:
+                               *cp2++ = *cp1;
+                               break;
+                     }
+                     if (*cp1 != '\0') {
+                        cp1++;
+                     }
+               }
+               *cp2 = '\0';
+               makeargv();
+               c = getcmd(margv[0]);
+               if (c == (struct cmd *)-1) {
+                       printf("?Ambiguous command\n");
+                       code = -1;
+               }
+               else if (c == 0) {
+                       printf("?Invalid command\n");
+                       code = -1;
+               }
+               else if (c->c_conn && !connected) {
+                       printf("Not connected.\n");
+                       code = -1;
+               }
+               else {
+                       if (verbose) {
+                               printf("%s\n",line);
+                       }
+                       (*c->c_handler)(margc, margv);
+                       if (bell && c->c_bell) {
+                               (void) putchar('\007');
+                       }
+                       (void) strcpy(line, line2);
+                       makeargv();
+                       argc = margc;
+                       argv = margv;
+               }
+               if (cp1 != macros[i].mac_end) {
+                       cp1++;
+               }
+       }
+       if (loopflg && ++count < argc) {
+               goto TOP;
+       }
+}
diff --git a/ftp.tproj/extern.h b/ftp.tproj/extern.h
new file mode 100644 (file)
index 0000000..e23f324
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1994 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)extern.h    8.3 (Berkeley) 10/9/94
+ */
+
+struct timeval;
+struct fd_set;
+
+void    abort_remote __P((FILE *));
+void    abortpt __P(());
+void    abortrecv __P(());
+void    abortsend __P(());
+void   account __P((int, char **));
+int    another __P((int *, char ***, char *));
+void   blkfree __P((char **));
+void   cd __P((int, char **));
+void   cdup __P((int, char **));
+void   changetype __P((int, int));
+void   cmdabort __P(());
+void   cmdscanner __P((int));
+int    command __P((const char *, ...));
+int    confirm __P((char *, char *));
+FILE   *dataconn __P((char *));
+void   delete __P((int, char **));
+void   disconnect __P((int, char **));
+void   do_chmod __P((int, char **));
+void   do_umask __P((int, char **));
+void   domacro __P((int, char **));
+char   *domap __P((char *));
+void   doproxy __P((int, char **));
+char   *dotrans __P((char *));
+int     empty __P((struct fd_set *, int));
+void   fatal __P((char *));
+void   get __P((int, char **));
+struct cmd *getcmd __P((char *));
+int    getit __P((int, char **, int, char *));
+int    getreply __P((int));
+int    globulize __P((char **));
+char   *gunique __P((char *));
+void   help __P((int, char **));
+char   *hookup __P((char *, int));
+void   idle __P((int, char **));
+int     initconn __P((void));
+void   intr __P(());
+void   lcd __P((int, char **));
+int    login __P((char *));
+void   lostpeer __P(());
+void   ls __P((int, char **));
+void   mabort __P((int));
+void   macdef __P((int, char **));
+void   makeargv __P((void));
+void   makedir __P((int, char **));
+void   mdelete __P((int, char **));
+void   mget __P((int, char **));
+void   mls __P((int, char **));
+void   modtime __P((int, char **));
+void   mput __P((int, char **));
+char   *onoff __P((int));
+void   newer __P((int, char **));
+void   proxabort __P(());
+void    proxtrans __P((char *, char *, char *));
+void    psabort __P(());
+void    pswitch __P((int));
+void    ptransfer __P((char *, long, struct timeval *, struct timeval *));
+void   put __P((int, char **));
+void   pwd __P((int, char **));
+void   quit __P((int, char **));
+void   quote __P((int, char **));
+void   quote1 __P((char *, int, char **));
+void    recvrequest __P((char *, char *, char *, char *, int));
+void   reget __P((int, char **));
+char   *remglob __P((char **, int));
+void   removedir __P((int, char **));
+void   renamefile __P((int, char **));
+void    reset __P((int, char **));
+void   restart __P((int, char **));
+void   rmthelp __P((int, char **));
+void   rmtstatus __P((int, char **));
+int    ruserpass __P((char *, char **, char **, char **));
+void    sendrequest __P((char *, char *, char *, int));
+void   setascii __P((int, char **));
+void   setbell __P((int, char **));
+void   setbinary __P((int, char **));
+void   setcase __P((int, char **));
+void   setcr __P((int, char **));
+void   setdebug __P((int, char **));
+void   setform __P((int, char **));
+void   setftmode __P((int, char **));
+void   setglob __P((int, char **));
+void   sethash __P((int, char **));
+void   setnmap __P((int, char **));
+void   setntrans __P((int, char **));
+void   setpassive __P((int, char **));
+void   setpeer __P((int, char **));
+void   setport __P((int, char **));
+void   setprompt __P((int, char **));
+void   setrunique __P((int, char **));
+void   setstruct __P((int, char **));
+void   setsunique __P((int, char **));
+void   settenex __P((int, char **));
+void   settrace __P((int, char **));
+void   settype __P((int, char **));
+void   setverbose __P((int, char **));
+void   shell __P((int, char **));
+void   site __P((int, char **));
+void   sizecmd __P((int, char **));
+char   *slurpstring __P((void));
+void   status __P((int, char **));
+void   syst __P((int, char **));
+void    tvsub __P((struct timeval *, struct timeval *, struct timeval *));
+void   user __P((int, char **));
+
+extern jmp_buf abortprox;
+extern int     abrtflag;
+extern struct  cmd cmdtab[];
+extern FILE    *cout;
+extern int     data;
+extern char    *home;
+extern jmp_buf jabort;
+extern int     proxy;
+extern char    reply_string[];
+extern off_t   restart_point;
+extern int     NCMDS;
diff --git a/ftp.tproj/ftp.1 b/ftp.tproj/ftp.1
new file mode 100644 (file)
index 0000000..79dcbae
--- /dev/null
@@ -0,0 +1,1157 @@
+.\" Copyright (c) 1985, 1989, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)ftp.1       8.3 (Berkeley) 10/9/94
+.\"
+.Dd October 9, 1994
+.Dt FTP 1
+.Os BSD 4.2
+.Sh NAME
+.Nm ftp
+.Nd
+.Tn ARPANET
+file transfer program
+.Sh SYNOPSIS
+.Nm ftp
+.Op Fl v
+.Op Fl d
+.Op Fl i
+.Op Fl n
+.Op Fl g
+.Op Ar host
+.Sh DESCRIPTION
+.Nm Ftp
+is the user interface to the
+.Tn ARPANET
+standard File Transfer Protocol.
+The program allows a user to transfer files to and from a
+remote network site.
+.Pp
+Options may be specified at the command line, or to the
+command interpreter.
+.Bl -tag -width flag
+.It Fl v
+Verbose option forces
+.Nm ftp
+to show all responses from the remote server, as well
+as report on data transfer statistics.
+.It Fl n
+Restrains
+.Nm ftp
+from attempting \*(Lqauto-login\*(Rq upon initial connection.
+If auto-login is enabled,
+.Nm ftp
+will check the
+.Pa .netrc
+(see below) file in the user's home directory for an entry describing
+an account on the remote machine.
+If no entry exists,
+.Nm ftp
+will prompt for the remote machine login name (default is the user
+identity on the local machine), and, if necessary, prompt for a password
+and an account with which to login.
+.It Fl i
+Turns off interactive prompting during
+multiple file transfers.
+.It Fl d
+Enables debugging.
+.It Fl g
+Disables file name globbing.
+.El
+.Pp
+The client host with which
+.Nm ftp
+is to communicate may be specified on the command line.
+If this is done,
+.Nm ftp
+will immediately attempt to establish a connection to an
+.Tn FTP
+server on that host; otherwise,
+.Nm ftp
+will enter its command interpreter and await instructions
+from the user.
+When
+.Nm ftp
+is awaiting commands from the user the prompt
+.Ql ftp>
+is provided to the user.
+The following commands are recognized
+by
+.Nm ftp  :
+.Bl -tag -width Fl
+.It Ic \&! Op Ar command Op Ar args
+Invoke an interactive shell on the local machine.
+If there are arguments, the first is taken to be a command to execute
+directly, with the rest of the arguments as its arguments.
+.It Ic \&$ Ar macro-name Op Ar args
+Execute the macro
+.Ar macro-name
+that was defined with the
+.Ic macdef
+command.
+Arguments are passed to the macro unglobbed.
+.It Ic account Op Ar passwd
+Supply a supplemental password required by a remote system for access
+to resources once a login has been successfully completed.
+If no argument is included, the user will be prompted for an account
+password in a non-echoing input mode.
+.It Ic append Ar local-file Op Ar remote-file
+Append a local file to a file on the remote machine.
+If
+.Ar remote-file
+is left unspecified, the local file name is used in naming the
+remote file after being altered by any
+.Ic ntrans
+or
+.Ic nmap
+setting.
+File transfer uses the current settings for
+.Ic type  ,
+.Ic format ,
+.Ic mode  ,
+and
+.Ic structure .
+.It Ic ascii
+Set the file transfer
+.Ic type
+to network
+.Tn ASCII .
+This is the default type.
+.It Ic bell
+Arrange that a bell be sounded after each file transfer
+command is completed.
+.It Ic binary
+Set the file transfer
+.Ic type
+to support binary image transfer.
+.It Ic bye
+Terminate the
+.Tn FTP
+session with the remote server
+and exit
+.Nm ftp  .
+An end of file will also terminate the session and exit.
+.It Ic case
+Toggle remote computer file name case mapping during
+.Ic mget
+commands.
+When
+.Ic case
+is on (default is off), remote computer file names with all letters in
+upper case are written in the local directory with the letters mapped
+to lower case.
+.It Ic \&cd Ar remote-directory
+Change the working directory on the remote machine
+to
+.Ar remote-directory  .
+.It Ic cdup
+Change the remote machine working directory to the parent of the
+current remote machine working directory.
+.It Ic chmod Ar mode file-name
+Change the permission modes of the file
+.Ar file-name
+on the remote
+sytem to
+.Ar mode  .
+.It Ic close
+Terminate the
+.Tn FTP
+session with the remote server, and
+return to the command interpreter.
+Any defined macros are erased.
+.It Ic \&cr
+Toggle carriage return stripping during
+ascii type file retrieval.
+Records are denoted by a carriage return/linefeed sequence
+during ascii type file transfer.
+When
+.Ic \&cr
+is on (the default), carriage returns are stripped from this
+sequence to conform with the
+.Ux
+single linefeed record
+delimiter.
+Records on
+.Pf non\- Ns Ux
+remote systems may contain single linefeeds;
+when an ascii type transfer is made, these linefeeds may be
+distinguished from a record delimiter only when
+.Ic \&cr
+is off.
+.It Ic delete Ar remote-file
+Delete the file
+.Ar remote-file
+on the remote machine.
+.It Ic debug Op Ar debug-value
+Toggle debugging mode.
+If an optional
+.Ar debug-value
+is specified it is used to set the debugging level.
+When debugging is on,
+.Nm ftp
+prints each command sent to the remote machine, preceded
+by the string
+.Ql \-\->
+.It Xo
+.Ic dir
+.Op Ar remote-directory
+.Op Ar local-file
+.Xc
+Print a listing of the directory contents in the
+directory,
+.Ar remote-directory  ,
+and, optionally, placing the output in
+.Ar local-file  .
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic dir
+output.
+If no directory is specified, the current working
+directory on the remote machine is used.
+If no local
+file is specified, or
+.Ar local-file
+is
+.Fl  ,
+output comes to the terminal.
+.It Ic disconnect
+A synonym for
+.Ar close  .
+.It Ic form Ar format
+Set the file transfer
+.Ic form
+to
+.Ar format  .
+The default format is \*(Lqfile\*(Rq.
+.It Ic get Ar remote-file Op Ar local-file
+Retrieve the
+.Ar remote-file
+and store it on the local machine.
+If the local
+file name is not specified, it is given the same
+name it has on the remote machine, subject to
+alteration by the current
+.Ic case  ,
+.Ic ntrans ,
+and
+.Ic nmap
+settings.
+The current settings for
+.Ic type  ,
+.Ic form ,
+.Ic mode  ,
+and
+.Ic structure
+are used while transferring the file.
+.It Ic glob
+Toggle filename expansion for
+.Ic mdelete  ,
+.Ic mget
+and
+.Ic mput  .
+If globbing is turned off with
+.Ic glob  ,
+the file name arguments
+are taken literally and not expanded.
+Globbing for
+.Ic mput
+is done as in
+.Xr csh 1 .
+For
+.Ic mdelete
+and
+.Ic mget  ,
+each remote file name is expanded
+separately on the remote machine and the lists are not merged.
+Expansion of a directory name is likely to be
+different from expansion of the name of an ordinary file:
+the exact result depends on the foreign operating system and ftp server,
+and can be previewed by doing
+.Ql mls remote-files \-
+Note:
+.Ic mget
+and
+.Ic mput
+are not meant to transfer
+entire directory subtrees of files.
+That can be done by
+transferring a
+.Xr tar 1
+archive of the subtree (in binary mode).
+.It Ic hash
+Toggle hash-sign (``#'') printing for each data block
+transferred.
+The size of a data block is 1024 bytes.
+.It Ic help Op Ar command
+Print an informative message about the meaning of
+.Ar command  .
+If no argument is given,
+.Nm ftp
+prints a list of the known commands.
+.It Ic idle Op Ar seconds
+Set the inactivity timer on the remote server to
+.Ar seconds
+seconds.
+If
+.Ar seconds
+is omitted, the current inactivity timer is printed.
+.It Ic lcd Op Ar directory
+Change the working directory on the local machine.
+If
+no
+.Ar directory
+is specified, the user's home directory is used.
+.It Xo
+.Ic \&ls
+.Op Ar remote-directory
+.Op Ar local-file
+.Xc
+Print a listing of the contents of a
+directory on the remote machine.
+The listing includes any system-dependent information that the server
+chooses to include; for example, most
+.Ux
+systems will produce
+output from the command
+.Ql ls \-l .
+(See also
+.Ic nlist . )
+If
+.Ar remote-directory
+is left unspecified, the current working directory is used.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic \&ls
+output.
+If no local file is specified, or if
+.Ar local-file
+is
+.Sq Fl ,
+the output is sent to the terminal.
+.It Ic macdef Ar macro-name
+Define a macro.
+Subsequent lines are stored as the macro
+.Ar macro-name  ;
+a null line (consecutive newline characters
+in a file or
+carriage returns from the terminal) terminates macro input mode.
+There is a limit of 16 macros and 4096 total characters in all
+defined macros.
+Macros remain defined until a
+.Ic close
+command is executed.
+The macro processor interprets `$' and `\e' as special characters.
+A `$' followed by a number (or numbers) is replaced by the
+corresponding argument on the macro invocation command line.
+A `$' followed by an `i' signals that macro processor that the
+executing macro is to be looped.
+On the first pass `$i' is
+replaced by the first argument on the macro invocation command line,
+on the second pass it is replaced by the second argument, and so on.
+A `\e' followed by any character is replaced by that character.
+Use the `\e' to prevent special treatment of the `$'.
+.It Ic mdelete Op Ar remote-files
+Delete the
+.Ar remote-files
+on the remote machine.
+.It Ic mdir Ar remote-files local-file
+Like
+.Ic dir  ,
+except multiple remote files may be specified.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic mdir
+output.
+.It Ic mget Ar remote-files
+Expand the
+.Ar remote-files
+on the remote machine
+and do a
+.Ic get
+for each file name thus produced.
+See
+.Ic glob
+for details on the filename expansion.
+Resulting file names will then be processed according to
+.Ic case  ,
+.Ic ntrans ,
+and
+.Ic nmap
+settings.
+Files are transferred into the local working directory,
+which can be changed with
+.Ql lcd directory ;
+new local directories can be created with
+.Ql "\&! mkdir directory" .
+.It Ic mkdir Ar directory-name
+Make a directory on the remote machine.
+.It Ic mls Ar remote-files local-file
+Like
+.Ic nlist  ,
+except multiple remote files may be specified,
+and the
+.Ar local-file
+must be specified.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic mls
+output.
+.It Ic mode Op Ar mode-name
+Set the file transfer
+.Ic mode
+to
+.Ar mode-name  .
+The default mode is \*(Lqstream\*(Rq mode.
+.It Ic modtime Ar file-name
+Show the last modification time of the file on the remote machine.
+.It Ic mput Ar local-files
+Expand wild cards in the list of local files given as arguments
+and do a
+.Ic put
+for each file in the resulting list.
+See
+.Ic glob
+for details of filename expansion.
+Resulting file names will then be processed according to
+.Ic ntrans
+and
+.Ic nmap
+settings.
+.It Ic newer Ar file-name
+Get the file only if the modification time of the remote file is more
+recent that the file on the current system.
+If the file does not
+exist on the current system, the remote file is considered
+.Ic newer  .
+Otherwise, this command is identical to
+.Ar get  .
+.It Xo
+.Ic nlist
+.Op Ar remote-directory
+.Op Ar local-file
+.Xc
+Print a  list of the files in a
+directory on the remote machine.
+If
+.Ar remote-directory
+is left unspecified, the current working directory is used.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic nlist
+output.
+If no local file is specified, or if
+.Ar local-file
+is
+.Fl  ,
+the output is sent to the terminal.
+.It Ic nmap Op Ar inpattern outpattern
+Set or unset the filename mapping mechanism.
+If no arguments are specified, the filename mapping mechanism is unset.
+If arguments are specified, remote filenames are mapped during
+.Ic mput
+commands and
+.Ic put
+commands issued without a specified remote target filename.
+If arguments are specified, local filenames are mapped during
+.Ic mget
+commands and
+.Ic get
+commands issued without a specified local target filename.
+This command is useful when connecting to a
+.No non\- Ns Ux
+remote computer
+with different file naming conventions or practices.
+The mapping follows the pattern set by
+.Ar inpattern
+and
+.Ar outpattern  .
+.Op Ar Inpattern
+is a template for incoming filenames (which may have already been
+processed according to the
+.Ic ntrans
+and
+.Ic case
+settings).
+Variable templating is accomplished by including the
+sequences `$1', `$2', ..., `$9' in
+.Ar inpattern  .
+Use `\\' to prevent this special treatment of the `$' character.
+All other characters are treated literally, and are used to determine the
+.Ic nmap
+.Op Ar inpattern
+variable values.
+For example, given
+.Ar inpattern
+$1.$2 and the remote file name "mydata.data", $1 would have the value
+"mydata", and $2 would have the value "data".
+The
+.Ar outpattern
+determines the resulting mapped filename.
+The sequences `$1', `$2', ...., `$9' are replaced by any value resulting
+from the
+.Ar inpattern
+template.
+The sequence `$0' is replace by the original filename.
+Additionally, the sequence
+.Ql Op Ar seq1 , Ar seq2
+is replaced by
+.Op Ar seq1
+if
+.Ar seq1
+is not a null string; otherwise it is replaced by
+.Ar seq2 .
+For example, the command
+.Pp
+.Bd -literal -offset indent -compact
+nmap $1.$2.$3 [$1,$2].[$2,file]
+.Ed
+.Pp
+would yield
+the output filename "myfile.data" for input filenames "myfile.data" and
+"myfile.data.old", "myfile.file" for the input filename "myfile", and
+"myfile.myfile" for the input filename ".myfile".
+Spaces may be included in
+.Ar outpattern  ,
+as in the example: `nmap $1 sed "s/  *$//" > $1' .
+Use the `\e' character to prevent special treatment
+of the `$','[','[', and `,' characters.
+.It Ic ntrans Op Ar inchars Op Ar outchars
+Set or unset the filename character translation mechanism.
+If no arguments are specified, the filename character
+translation mechanism is unset.
+If arguments are specified, characters in
+remote filenames are translated during
+.Ic mput
+commands and
+.Ic put
+commands issued without a specified remote target filename.
+If arguments are specified, characters in
+local filenames are translated during
+.Ic mget
+commands and
+.Ic get
+commands issued without a specified local target filename.
+This command is useful when connecting to a
+.No non\- Ns Ux
+remote computer
+with different file naming conventions or practices.
+Characters in a filename matching a character in
+.Ar inchars
+are replaced with the corresponding character in
+.Ar outchars  .
+If the character's position in
+.Ar inchars
+is longer than the length of
+.Ar outchars  ,
+the character is deleted from the file name.
+.It Ic open Ar host Op Ar port
+Establish a connection to the specified
+.Ar host
+.Tn FTP
+server.
+An optional port number may be supplied,
+in which case,
+.Nm ftp
+will attempt to contact an
+.Tn FTP
+server at that port.
+If the
+.Ic auto-login
+option is on (default),
+.Nm ftp
+will also attempt to automatically log the user in to
+the
+.Tn FTP
+server (see below).
+.It Ic passive
+Toggle passive mode.  If passive mode is turned on
+(default is off), the ftp client will
+send a
+.Dv PASV
+command for all data connections instead of the usual
+.Dv PORT
+command.  The
+.Dv PASV
+command requests that the remote server open a port for the data connection
+and return the address of that port.  The remote server listens on that
+port and the client connects to it.  When using the more traditional
+.Dv PORT
+command, the client listens on a port and sends that address to the remote
+server, who connects back to it.  Passive mode is useful when using
+.Nm ftp
+through a gateway router or host that controls the directionality of
+traffic.
+(Note that though ftp servers are required to support the
+.Dv PASV
+command by RFC 1123, some do not.)
+.It Ic prompt
+Toggle interactive prompting.
+Interactive prompting
+occurs during multiple file transfers to allow the
+user to selectively retrieve or store files.
+If prompting is turned off (default is on), any
+.Ic mget
+or
+.Ic mput
+will transfer all files, and any
+.Ic mdelete
+will delete all files.
+.It Ic proxy Ar ftp-command
+Execute an ftp command on a secondary control connection.
+This command allows simultaneous connection to two remote ftp
+servers for transferring files between the two servers.
+The first
+.Ic proxy
+command should be an
+.Ic open  ,
+to establish the secondary control connection.
+Enter the command "proxy ?" to see other ftp commands executable on the
+secondary connection.
+The following commands behave differently when prefaced by
+.Ic proxy  :
+.Ic open
+will not define new macros during the auto-login process,
+.Ic close
+will not erase existing macro definitions,
+.Ic get
+and
+.Ic mget
+transfer files from the host on the primary control connection
+to the host on the secondary control connection, and
+.Ic put  ,
+.Ic mput ,
+and
+.Ic append
+transfer files from the host on the secondary control connection
+to the host on the primary control connection.
+Third party file transfers depend upon support of the ftp protocol
+.Dv PASV
+command by the server on the secondary control connection.
+.It Ic put Ar local-file Op Ar remote-file
+Store a local file on the remote machine.
+If
+.Ar remote-file
+is left unspecified, the local file name is used
+after processing according to any
+.Ic ntrans
+or
+.Ic nmap
+settings
+in naming the remote file.
+File transfer uses the
+current settings for
+.Ic type  ,
+.Ic format ,
+.Ic mode  ,
+and
+.Ic structure  .
+.It Ic pwd
+Print the name of the current working directory on the remote
+machine.
+.It Ic quit
+A synonym for
+.Ic bye  .
+.It Ic quote Ar arg1 arg2 ...
+The arguments specified are sent, verbatim, to the remote
+.Tn FTP
+server.
+.It Ic recv Ar remote-file Op Ar local-file
+A synonym for get.
+.It Ic reget Ar remote-file Op Ar local-file
+Reget acts like get, except that if
+.Ar local-file
+exists and is
+smaller than
+.Ar remote-file  ,
+.Ar local-file
+is presumed to be
+a partially transferred copy of
+.Ar remote-file
+and the transfer
+is continued from the apparent point of failure.
+This command
+is useful when transferring very large files over networks that
+are prone to dropping connections.
+.It Ic remotehelp Op Ar command-name
+Request help from the remote
+.Tn FTP
+server.
+If a
+.Ar command-name
+is specified it is supplied to the server as well.
+.It Ic remotestatus Op Ar file-name
+With no arguments, show status of remote machine.
+If
+.Ar file-name
+is specified, show status of
+.Ar file-name
+on remote machine.
+.It Xo
+.Ic rename
+.Op Ar from
+.Op Ar to
+.Xc
+Rename the file
+.Ar from
+on the remote machine, to the file
+.Ar to  .
+.It Ic reset
+Clear reply queue.
+This command re-synchronizes command/reply sequencing with the remote
+ftp server.
+Resynchronization may be necessary following a violation of the ftp protocol
+by the remote server.
+.It Ic restart Ar marker
+Restart the immediately following
+.Ic get
+or
+.Ic put
+at the
+indicated
+.Ar marker  .
+On
+.Ux
+systems, marker is usually a byte
+offset into the file.
+.It Ic rmdir Ar directory-name
+Delete a directory on the remote machine.
+.It Ic runique
+Toggle storing of files on the local system with unique filenames.
+If a file already exists with a name equal to the target
+local filename for a
+.Ic get
+or
+.Ic mget
+command, a ".1" is appended to the name.
+If the resulting name matches another existing file,
+a ".2" is appended to the original name.
+If this process continues up to ".99", an error
+message is printed, and the transfer does not take place.
+The generated unique filename will be reported.
+Note that
+.Ic runique
+will not affect local files generated from a shell command
+(see below).
+The default value is off.
+.It Ic send Ar local-file Op Ar remote-file
+A synonym for put.
+.It Ic sendport
+Toggle the use of
+.Dv PORT
+commands.
+By default,
+.Nm ftp
+will attempt to use a
+.Dv PORT
+command when establishing
+a connection for each data transfer.
+The use of
+.Dv PORT
+commands can prevent delays
+when performing multiple file transfers.
+If the
+.Dv PORT
+command fails,
+.Nm ftp
+will use the default data port.
+When the use of
+.Dv PORT
+commands is disabled, no attempt will be made to use
+.Dv PORT
+commands for each data transfer.
+This is useful
+for certain
+.Tn FTP
+implementations which do ignore
+.Dv PORT
+commands but, incorrectly, indicate they've been accepted.
+.It Ic site Ar arg1 arg2 ...
+The arguments specified are sent, verbatim, to the remote
+.Tn FTP
+server as a
+.Dv SITE
+command.
+.It Ic size Ar file-name
+Return size of
+.Ar file-name
+on remote machine.
+.It Ic status
+Show the current status of
+.Nm ftp  .
+.It Ic struct Op Ar struct-name
+Set the file transfer
+.Ar structure
+to
+.Ar struct-name .
+By default \*(Lqstream\*(Rq structure is used.
+.It Ic sunique
+Toggle storing of files on remote machine under unique file names.
+Remote ftp server must support ftp protocol
+.Dv STOU
+command for
+successful completion.
+The remote server will report unique name.
+Default value is off.
+.It Ic system
+Show the type of operating system running on the remote machine.
+.It Ic tenex
+Set the file transfer type to that needed to
+talk to
+.Tn TENEX
+machines.
+.It Ic trace
+Toggle packet tracing.
+.It Ic type Op Ar type-name
+Set the file transfer
+.Ic type
+to
+.Ar type-name  .
+If no type is specified, the current type
+is printed.
+The default type is network
+.Tn ASCII .
+.It Ic umask Op Ar newmask
+Set the default umask on the remote server to
+.Ar newmask  .
+If
+.Ar newmask
+is omitted, the current umask is printed.
+.It Xo
+.Ic user Ar user-name
+.Op Ar password
+.Op Ar account
+.Xc
+Identify yourself to the remote
+.Tn FTP
+server.
+If the
+.Ar password
+is not specified and the server requires it,
+.Nm ftp
+will prompt the user for it (after disabling local echo).
+If an
+.Ar account
+field is not specified, and the
+.Tn FTP
+server
+requires it, the user will be prompted for it.
+If an
+.Ar account
+field is specified, an account command will
+be relayed to the remote server after the login sequence
+is completed if the remote server did not require it
+for logging in.
+Unless
+.Nm ftp
+is invoked with \*(Lqauto-login\*(Rq disabled, this
+process is done automatically on initial connection to
+the
+.Tn FTP
+server.
+.It Ic verbose
+Toggle verbose mode.
+In verbose mode, all responses from
+the
+.Tn FTP
+server are displayed to the user.
+In addition,
+if verbose is on, when a file transfer completes, statistics
+regarding the efficiency of the transfer are reported.
+By default,
+verbose is on.
+.It Ic ? Op Ar command
+A synonym for help.
+.El
+.Pp
+Command arguments which have embedded spaces may be quoted with
+quote `"' marks.
+.Sh ABORTING A FILE TRANSFER
+To abort a file transfer, use the terminal interrupt key
+(usually Ctrl-C).
+Sending transfers will be immediately halted.
+Receiving transfers will be halted by sending a ftp protocol
+.Dv ABOR
+command to the remote server, and discarding any further data received.
+The speed at which this is accomplished depends upon the remote
+server's support for
+.Dv ABOR
+processing.
+If the remote server does not support the
+.Dv ABOR
+command, an
+.Ql ftp>
+prompt will not appear until the remote server has completed
+sending the requested file.
+.Pp
+The terminal interrupt key sequence will be ignored when
+.Nm ftp
+has completed any local processing and is awaiting a reply
+from the remote server.
+A long delay in this mode may result from the ABOR processing described
+above, or from unexpected behavior by the remote server, including
+violations of the ftp protocol.
+If the delay results from unexpected remote server behavior, the local
+.Nm ftp
+program must be killed by hand.
+.Sh FILE NAMING CONVENTIONS
+Files specified as arguments to
+.Nm ftp
+commands are processed according to the following rules.
+.Bl -enum
+.It
+If the file name
+.Sq Fl
+is specified, the
+.Ar stdin
+(for reading) or
+.Ar stdout
+(for writing) is used.
+.It
+If the first character of the file name is
+.Sq \&| ,
+the
+remainder of the argument is interpreted as a shell command.
+.Nm Ftp
+then forks a shell, using
+.Xr popen 3
+with the argument supplied, and reads (writes) from the stdout
+(stdin).
+If the shell command includes spaces, the argument
+must be quoted; e.g.
+\*(Lq" ls -lt"\*(Rq.
+A particularly
+useful example of this mechanism is: \*(Lqdir more\*(Rq.
+.It
+Failing the above checks, if ``globbing'' is enabled,
+local file names are expanded
+according to the rules used in the
+.Xr csh  1  ;
+c.f. the
+.Ic glob
+command.
+If the
+.Nm ftp
+command expects a single local file (.e.g.
+.Ic put  ) ,
+only the first filename generated by the "globbing" operation is used.
+.It
+For
+.Ic mget
+commands and
+.Ic get
+commands with unspecified local file names, the local filename is
+the remote filename, which may be altered by a
+.Ic case  ,
+.Ic ntrans ,
+or
+.Ic nmap
+setting.
+The resulting filename may then be altered if
+.Ic runique
+is on.
+.It
+For
+.Ic mput
+commands and
+.Ic put
+commands with unspecified remote file names, the remote filename is
+the local filename, which may be altered by a
+.Ic ntrans
+or
+.Ic nmap
+setting.
+The resulting filename may then be altered by the remote server if
+.Ic sunique
+is on.
+.El
+.Sh FILE TRANSFER PARAMETERS
+The FTP specification specifies many parameters which may
+affect a file transfer.
+The
+.Ic type
+may be one of \*(Lqascii\*(Rq, \*(Lqimage\*(Rq (binary),
+\*(Lqebcdic\*(Rq, and \*(Lqlocal byte size\*(Rq (for
+.Tn PDP Ns -10's
+and
+.Tn PDP Ns -20's
+mostly).
+.Nm Ftp
+supports the ascii and image types of file transfer,
+plus local byte size 8 for
+.Ic tenex
+mode transfers.
+.Pp
+.Nm Ftp
+supports only the default values for the remaining
+file transfer parameters:
+.Ic mode  ,
+.Ic form ,
+and
+.Ic struct  .
+.Sh THE .netrc FILE
+The
+.Pa .netrc
+file contains login and initialization information
+used by the auto-login process.
+It resides in the user's home directory.
+The following tokens are recognized; they may be separated by spaces,
+tabs, or new-lines:
+.Bl -tag -width password
+.It Ic machine Ar name
+Identify a remote machine
+.Ar name .
+The auto-login process searches the
+.Pa .netrc
+file for a
+.Ic machine
+token that matches the remote machine specified on the
+.Nm ftp
+command line or as an
+.Ic open
+command argument.
+Once a match is made, the subsequent
+.Pa .netrc
+tokens are processed,
+stopping when the end of file is reached or another
+.Ic machine
+or a
+.Ic default
+token is encountered.
+.It Ic default
+This is the same as
+.Ic machine
+.Ar name
+except that
+.Ic default
+matches any name.
+There can be only one
+.Ic default
+token, and it must be after all
+.Ic machine
+tokens.
+This is normally used as:
+.Pp
+.Dl default login anonymous password user@site
+.Pp
+thereby giving the user
+.Ar automatic
+anonymous ftp login to
+machines not specified in
+.Pa .netrc .
+This can be overridden
+by using the
+.Fl n
+flag to disable auto-login.
+.It Ic login Ar name
+Identify a user on the remote machine.
+If this token is present, the auto-login process will initiate
+a login using the specified
+.Ar name .
+.It Ic password Ar string
+Supply a password.
+If this token is present, the auto-login process will supply the
+specified string if the remote server requires a password as part
+of the login process.
+Note that if this token is present in the
+.Pa .netrc
+file for any user other
+than
+.Ar anonymous  ,
+.Nm ftp
+will abort the auto-login process if the
+.Pa .netrc
+is readable by
+anyone besides the user.
+.It Ic account Ar string
+Supply an additional account password.
+If this token is present, the auto-login process will supply the
+specified string if the remote server requires an additional
+account password, or the auto-login process will initiate an
+.Dv ACCT
+command if it does not.
+.It Ic macdef Ar name
+Define a macro.
+This token functions like the
+.Nm ftp
+.Ic macdef
+command functions.
+A macro is defined with the specified name; its contents begin with the
+next
+.Pa .netrc
+line and continue until a null line (consecutive new-line
+characters) is encountered.
+If a macro named
+.Ic init
+is defined, it is automatically executed as the last step in the
+auto-login process.
+.El
+.Sh ENVIRONMENT
+.Nm Ftp
+utilizes the following environment variables.
+.Bl -tag -width Fl
+.It Ev HOME
+For default location of a
+.Pa .netrc
+file, if one exists.
+.It Ev SHELL
+For default shell.
+.El
+.Sh SEE ALSO
+.Xr ftpd 8
+.Sh HISTORY
+The
+.Nm ftp
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+Correct execution of many commands depends upon proper behavior
+by the remote server.
+.Pp
+An error in the treatment of carriage returns
+in the
+.Bx 4.2
+ascii-mode transfer code
+has been corrected.
+This correction may result in incorrect transfers of binary files
+to and from
+.Bx 4.2
+servers using the ascii type.
+Avoid this problem by using the binary image type.
diff --git a/ftp.tproj/ftp.c b/ftp.tproj/ftp.c
new file mode 100644 (file)
index 0000000..a2a54a9
--- /dev/null
@@ -0,0 +1,1542 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <arpa/ftp.h>
+#include <arpa/telnet.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "ftp_var.h"
+
+extern int h_errno;
+
+struct sockaddr_in hisctladdr;
+struct sockaddr_in data_addr;
+int    data = -1;
+int    abrtflag = 0;
+jmp_buf        ptabort;
+int    ptabflg;
+int    ptflag = 0;
+struct sockaddr_in myctladdr;
+off_t  restart_point = 0;
+
+FILE   *cin, *cout;
+
+char *
+hookup(host, port)
+       char *host;
+       int port;
+{
+       struct hostent *hp = 0;
+       int s, len, tos;
+       static char hostnamebuf[80];
+
+       memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
+       hisctladdr.sin_addr.s_addr = inet_addr(host);
+       if (hisctladdr.sin_addr.s_addr != -1) {
+               hisctladdr.sin_family = AF_INET;
+               (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
+       } else {
+               hp = gethostbyname(host);
+               if (hp == NULL) {
+                       warnx("%s: %s", host, hstrerror(h_errno));
+                       code = -1;
+                       return ((char *) 0);
+               }
+               hisctladdr.sin_family = hp->h_addrtype;
+               memmove((caddr_t)&hisctladdr.sin_addr,
+                               hp->h_addr_list[0], hp->h_length);
+               (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
+       }
+       hostname = hostnamebuf;
+       s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
+       if (s < 0) {
+               warn("socket");
+               code = -1;
+               return (0);
+       }
+       hisctladdr.sin_port = port;
+       while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
+               if (hp && hp->h_addr_list[1]) {
+                       int oerrno = errno;
+                       char *ia;
+
+                       ia = inet_ntoa(hisctladdr.sin_addr);
+                       errno = oerrno;
+                       warn("connect to address %s", ia);
+                       hp->h_addr_list++;
+                       memmove((caddr_t)&hisctladdr.sin_addr,
+                                       hp->h_addr_list[0], hp->h_length);
+                       fprintf(stdout, "Trying %s...\n",
+                               inet_ntoa(hisctladdr.sin_addr));
+                       (void) close(s);
+                       s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
+                       if (s < 0) {
+                               warn("socket");
+                               code = -1;
+                               return (0);
+                       }
+                       continue;
+               }
+               warn("connect");
+               code = -1;
+               goto bad;
+       }
+       len = sizeof (myctladdr);
+       if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
+               warn("getsockname");
+               code = -1;
+               goto bad;
+       }
+#ifdef IP_TOS
+       tos = IPTOS_LOWDELAY;
+       if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+               warn("setsockopt TOS (ignored)");
+#endif
+       cin = fdopen(s, "r");
+       cout = fdopen(s, "w");
+       if (cin == NULL || cout == NULL) {
+               warnx("fdopen failed.");
+               if (cin)
+                       (void) fclose(cin);
+               if (cout)
+                       (void) fclose(cout);
+               code = -1;
+               goto bad;
+       }
+       if (verbose)
+               printf("Connected to %s.\n", hostname);
+       if (getreply(0) > 2) {  /* read startup message from server */
+               if (cin)
+                       (void) fclose(cin);
+               if (cout)
+                       (void) fclose(cout);
+               code = -1;
+               goto bad;
+       }
+#ifdef SO_OOBINLINE
+       {
+       int on = 1;
+
+       if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
+               < 0 && debug) {
+                       warn("setsockopt");
+               }
+       }
+#endif /* SO_OOBINLINE */
+
+       return (hostname);
+bad:
+       (void) close(s);
+       return ((char *)0);
+}
+
+int
+login(host)
+       char *host;
+{
+       char tmp[80];
+       char *user, *pass, *acct;
+       int n, aflag = 0;
+
+       user = pass = acct = 0;
+       if (ruserpass(host, &user, &pass, &acct) < 0) {
+               code = -1;
+               return (0);
+       }
+       while (user == NULL) {
+               char *myname = getlogin();
+
+               if (myname == NULL) {
+                       struct passwd *pp = getpwuid(getuid());
+
+                       if (pp != NULL)
+                               myname = pp->pw_name;
+               }
+               if (myname)
+                       printf("Name (%s:%s): ", host, myname);
+               else
+                       printf("Name (%s): ", host);
+               (void) fgets(tmp, sizeof(tmp) - 1, stdin);
+               tmp[strlen(tmp) - 1] = '\0';
+               if (*tmp == '\0')
+                       user = myname;
+               else
+                       user = tmp;
+       }
+       n = command("USER %s", user);
+       if (n == CONTINUE) {
+               if (pass == NULL)
+                       pass = getpass("Password:");
+               n = command("PASS %s", pass);
+       }
+       if (n == CONTINUE) {
+               aflag++;
+               acct = getpass("Account:");
+               n = command("ACCT %s", acct);
+       }
+       if (n != COMPLETE) {
+               warnx("Login failed.");
+               return (0);
+       }
+       if (!aflag && acct != NULL)
+               (void) command("ACCT %s", acct);
+       if (proxy)
+               return (1);
+       for (n = 0; n < macnum; ++n) {
+               if (!strcmp("init", macros[n].mac_name)) {
+                       (void) strcpy(line, "$init");
+                       makeargv();
+                       domacro(margc, margv);
+                       break;
+               }
+       }
+       return (1);
+}
+
+void
+cmdabort()
+{
+
+       printf("\n");
+       (void) fflush(stdout);
+       abrtflag++;
+       if (ptflag)
+               longjmp(ptabort,1);
+}
+
+int command(const char *fmt, ...)
+{
+       va_list ap;
+       int r;
+       sig_t oldintr;
+
+       abrtflag = 0;
+       if (debug) {
+               printf("---> ");
+               va_start(ap, fmt);
+               if (strncmp("PASS ", fmt, 5) == 0)
+                       printf("PASS XXXX");
+               else 
+                       vfprintf(stdout, fmt, ap);
+               va_end(ap);
+               printf("\n");
+               (void) fflush(stdout);
+       }
+       if (cout == NULL) {
+               warn("No control connection for command");
+               code = -1;
+               return (0);
+       }
+       oldintr = signal(SIGINT, cmdabort);
+       va_start(ap, fmt);
+       vfprintf(cout, fmt, ap);
+       va_end(ap);
+       fprintf(cout, "\r\n");
+       (void) fflush(cout);
+       cpend = 1;
+       r = getreply(!strcmp(fmt, "QUIT"));
+       if (abrtflag && oldintr != SIG_IGN)
+               (*oldintr)(SIGINT);
+       (void) signal(SIGINT, oldintr);
+       return (r);
+}
+
+char reply_string[BUFSIZ];             /* last line of previous reply */
+
+int
+getreply(expecteof)
+       int expecteof;
+{
+       int c, n;
+       int dig;
+       int originalcode = 0, continuation = 0;
+       sig_t oldintr;
+       int pflag = 0;
+       char *cp, *pt = pasv;
+
+       oldintr = signal(SIGINT, cmdabort);
+       for (;;) {
+               dig = n = code = 0;
+               cp = reply_string;
+               while ((c = getc(cin)) != '\n') {
+                       if (c == IAC) {     /* handle telnet commands */
+                               switch (c = getc(cin)) {
+                               case WILL:
+                               case WONT:
+                                       c = getc(cin);
+                                       fprintf(cout, "%c%c%c", IAC, DONT, c);
+                                       (void) fflush(cout);
+                                       break;
+                               case DO:
+                               case DONT:
+                                       c = getc(cin);
+                                       fprintf(cout, "%c%c%c", IAC, WONT, c);
+                                       (void) fflush(cout);
+                                       break;
+                               default:
+                                       break;
+                               }
+                               continue;
+                       }
+                       dig++;
+                       if (c == EOF) {
+                               if (expecteof) {
+                                       (void) signal(SIGINT,oldintr);
+                                       code = 221;
+                                       return (0);
+                               }
+                               lostpeer();
+                               if (verbose) {
+                                       printf("421 Service not available, remote server has closed connection\n");
+                                       (void) fflush(stdout);
+                               }
+                               code = 421;
+                               return (4);
+                       }
+                       if (c != '\r' && (verbose > 0 ||
+                           (verbose > -1 && n == '5' && dig > 4))) {
+                               if (proxflag &&
+                                  (dig == 1 || dig == 5 && verbose == 0))
+                                       printf("%s:",hostname);
+                               (void) putchar(c);
+                       }
+                       if (dig < 4 && isdigit(c))
+                               code = code * 10 + (c - '0');
+                       if (!pflag && code == 227)
+                               pflag = 1;
+                       if (dig > 4 && pflag == 1 && isdigit(c))
+                               pflag = 2;
+                       if (pflag == 2) {
+                               if (c != '\r' && c != ')')
+                                       *pt++ = c;
+                               else {
+                                       *pt = '\0';
+                                       pflag = 3;
+                               }
+                       }
+                       if (dig == 4 && c == '-') {
+                               if (continuation)
+                                       code = 0;
+                               continuation++;
+                       }
+                       if (n == 0)
+                               n = c;
+                       if (cp < &reply_string[sizeof(reply_string) - 1])
+                               *cp++ = c;
+               }
+               if (verbose > 0 || verbose > -1 && n == '5') {
+                       (void) putchar(c);
+                       (void) fflush (stdout);
+               }
+               if (continuation && code != originalcode) {
+                       if (originalcode == 0)
+                               originalcode = code;
+                       continue;
+               }
+               *cp = '\0';
+               if (n != '1')
+                       cpend = 0;
+               (void) signal(SIGINT,oldintr);
+               if (code == 421 || originalcode == 421)
+                       lostpeer();
+               if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
+                       (*oldintr)(SIGINT);
+               return (n - '0');
+       }
+}
+
+int
+empty(mask, sec)
+       struct fd_set *mask;
+       int sec;
+{
+       struct timeval t;
+
+       t.tv_sec = (long) sec;
+       t.tv_usec = 0;
+       return (select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
+}
+
+jmp_buf        sendabort;
+
+void
+abortsend()
+{
+
+       mflag = 0;
+       abrtflag = 0;
+       printf("\nsend aborted\nwaiting for remote to finish abort\n");
+       (void) fflush(stdout);
+       longjmp(sendabort, 1);
+}
+
+#define HASHBYTES 1024
+
+void
+sendrequest(cmd, local, remote, printnames)
+       char *cmd, *local, *remote;
+       int printnames;
+{
+       struct stat st;
+       struct timeval start, stop;
+       int c, d;
+       FILE *fin, *dout = 0, *popen();
+       int (*closefunc) __P((FILE *));
+       sig_t oldintr, oldintp;
+       long bytes = 0, hashbytes = HASHBYTES;
+       char *lmode, buf[BUFSIZ], *bufp;
+
+       if (verbose && printnames) {
+               if (local && *local != '-')
+                       printf("local: %s ", local);
+               if (remote)
+                       printf("remote: %s\n", remote);
+       }
+       if (proxy) {
+               proxtrans(cmd, local, remote);
+               return;
+       }
+       if (curtype != type)
+               changetype(type, 0);
+       closefunc = NULL;
+       oldintr = NULL;
+       oldintp = NULL;
+       lmode = "w";
+       if (setjmp(sendabort)) {
+               while (cpend) {
+                       (void) getreply(0);
+               }
+               if (data >= 0) {
+                       (void) close(data);
+                       data = -1;
+               }
+               if (oldintr)
+                       (void) signal(SIGINT,oldintr);
+               if (oldintp)
+                       (void) signal(SIGPIPE,oldintp);
+               code = -1;
+               return;
+       }
+       oldintr = signal(SIGINT, abortsend);
+       if (strcmp(local, "-") == 0)
+               fin = stdin;
+       else if (*local == '|') {
+               oldintp = signal(SIGPIPE,SIG_IGN);
+               fin = popen(local + 1, "r");
+               if (fin == NULL) {
+                       warn("%s", local + 1);
+                       (void) signal(SIGINT, oldintr);
+                       (void) signal(SIGPIPE, oldintp);
+                       code = -1;
+                       return;
+               }
+               closefunc = pclose;
+       } else {
+               fin = fopen(local, "r");
+               if (fin == NULL) {
+                       warn("local: %s", local);
+                       (void) signal(SIGINT, oldintr);
+                       code = -1;
+                       return;
+               }
+               closefunc = fclose;
+               if (fstat(fileno(fin), &st) < 0 ||
+                   (st.st_mode&S_IFMT) != S_IFREG) {
+                       fprintf(stdout, "%s: not a plain file.\n", local);
+                       (void) signal(SIGINT, oldintr);
+                       fclose(fin);
+                       code = -1;
+                       return;
+               }
+       }
+       if (initconn()) {
+               (void) signal(SIGINT, oldintr);
+               if (oldintp)
+                       (void) signal(SIGPIPE, oldintp);
+               code = -1;
+               if (closefunc != NULL)
+                       (*closefunc)(fin);
+               return;
+       }
+       if (setjmp(sendabort))
+               goto abort;
+
+       if (restart_point &&
+           (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
+               int rc;
+
+               switch (curtype) {
+               case TYPE_A:
+                       rc = fseek(fin, (long) restart_point, SEEK_SET);
+                       break;
+               case TYPE_I:
+               case TYPE_L:
+                       rc = lseek(fileno(fin), restart_point, SEEK_SET);
+                       break;
+               }
+               if (rc < 0) {
+                       warn("local: %s", local);
+                       restart_point = 0;
+                       if (closefunc != NULL)
+                               (*closefunc)(fin);
+                       return;
+               }
+               if (command("REST %ld", (long) restart_point)
+                       != CONTINUE) {
+                       restart_point = 0;
+                       if (closefunc != NULL)
+                               (*closefunc)(fin);
+                       return;
+               }
+               restart_point = 0;
+               lmode = "r+w";
+       }
+       if (remote) {
+               if (command("%s %s", cmd, remote) != PRELIM) {
+                       (void) signal(SIGINT, oldintr);
+                       if (oldintp)
+                               (void) signal(SIGPIPE, oldintp);
+                       if (closefunc != NULL)
+                               (*closefunc)(fin);
+                       return;
+               }
+       } else
+               if (command("%s", cmd) != PRELIM) {
+                       (void) signal(SIGINT, oldintr);
+                       if (oldintp)
+                               (void) signal(SIGPIPE, oldintp);
+                       if (closefunc != NULL)
+                               (*closefunc)(fin);
+                       return;
+               }
+       dout = dataconn(lmode);
+       if (dout == NULL)
+               goto abort;
+       (void) gettimeofday(&start, (struct timezone *)0);
+       oldintp = signal(SIGPIPE, SIG_IGN);
+       switch (curtype) {
+
+       case TYPE_I:
+       case TYPE_L:
+               errno = d = 0;
+               while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
+                       bytes += c;
+                       for (bufp = buf; c > 0; c -= d, bufp += d)
+                               if ((d = write(fileno(dout), bufp, c)) <= 0)
+                                       break;
+                       if (hash) {
+                               while (bytes >= hashbytes) {
+                                       (void) putchar('#');
+                                       hashbytes += HASHBYTES;
+                               }
+                               (void) fflush(stdout);
+                       }
+               }
+               if (hash && bytes > 0) {
+                       if (bytes < HASHBYTES)
+                               (void) putchar('#');
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
+               }
+               if (c < 0)
+                       warn("local: %s", local);
+               if (d < 0) {
+                       if (errno != EPIPE) 
+                               warn("netout");
+                       bytes = -1;
+               }
+               break;
+
+       case TYPE_A:
+               while ((c = getc(fin)) != EOF) {
+                       if (c == '\n') {
+                               while (hash && (bytes >= hashbytes)) {
+                                       (void) putchar('#');
+                                       (void) fflush(stdout);
+                                       hashbytes += HASHBYTES;
+                               }
+                               if (ferror(dout))
+                                       break;
+                               (void) putc('\r', dout);
+                               bytes++;
+                       }
+                       (void) putc(c, dout);
+                       bytes++;
+       /*              if (c == '\r') {                                */
+       /*              (void)  putc('\0', dout);  // this violates rfc */
+       /*                      bytes++;                                */
+       /*              }                                               */      
+               }
+               if (hash) {
+                       if (bytes < hashbytes)
+                               (void) putchar('#');
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
+               }
+               if (ferror(fin))
+                       warn("local: %s", local);
+               if (ferror(dout)) {
+                       if (errno != EPIPE)
+                               warn("netout");
+                       bytes = -1;
+               }
+               break;
+       }
+       if (closefunc != NULL)
+               (*closefunc)(fin);
+       (void) fclose(dout);
+       (void) gettimeofday(&stop, (struct timezone *)0);
+       (void) getreply(0);
+       (void) signal(SIGINT, oldintr);
+       if (oldintp)
+               (void) signal(SIGPIPE, oldintp);
+       if (bytes > 0)
+               ptransfer("sent", bytes, &start, &stop);
+       return;
+abort:
+       (void) signal(SIGINT, oldintr);
+       if (oldintp)
+               (void) signal(SIGPIPE, oldintp);
+       if (!cpend) {
+               code = -1;
+               return;
+       }
+       if (data >= 0) {
+               (void) close(data);
+               data = -1;
+       }
+       if (dout)
+               (void) fclose(dout);
+       (void) getreply(0);
+       code = -1;
+       if (closefunc != NULL && fin != NULL)
+               (*closefunc)(fin);
+       (void) gettimeofday(&stop, (struct timezone *)0);
+       if (bytes > 0)
+               ptransfer("sent", bytes, &start, &stop);
+}
+
+jmp_buf        recvabort;
+
+void
+abortrecv()
+{
+
+       mflag = 0;
+       abrtflag = 0;
+       printf("\nreceive aborted\nwaiting for remote to finish abort\n");
+       (void) fflush(stdout);
+       longjmp(recvabort, 1);
+}
+
+void
+recvrequest(cmd, local, remote, lmode, printnames)
+       char *cmd, *local, *remote, *lmode;
+       int printnames;
+{
+       FILE *fout, *din = 0;
+       int (*closefunc) __P((FILE *));
+       sig_t oldintr, oldintp;
+       int c, d, is_retr, tcrflag, bare_lfs = 0;
+       static int bufsize;
+       static char *buf;
+       long bytes = 0, hashbytes = HASHBYTES;
+       struct timeval start, stop;
+       struct stat st;
+
+       is_retr = strcmp(cmd, "RETR") == 0;
+       if (is_retr && verbose && printnames) {
+               if (local && *local != '-')
+                       printf("local: %s ", local);
+               if (remote)
+                       printf("remote: %s\n", remote);
+       }
+       if (proxy && is_retr) {
+               proxtrans(cmd, local, remote);
+               return;
+       }
+       closefunc = NULL;
+       oldintr = NULL;
+       oldintp = NULL;
+       tcrflag = !crflag && is_retr;
+       if (setjmp(recvabort)) {
+               while (cpend) {
+                       (void) getreply(0);
+               }
+               if (data >= 0) {
+                       (void) close(data);
+                       data = -1;
+               }
+               if (oldintr)
+                       (void) signal(SIGINT, oldintr);
+               code = -1;
+               return;
+       }
+       oldintr = signal(SIGINT, abortrecv);
+       if (strcmp(local, "-") && *local != '|') {
+               if (access(local, 2) < 0) {
+                       char *dir = strrchr(local, '/');
+
+                       if (errno != ENOENT && errno != EACCES) {
+                               warn("local: %s", local);
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
+                       }
+                       if (dir != NULL)
+                               *dir = 0;
+                       d = access(dir ? local : ".", 2);
+                       if (dir != NULL)
+                               *dir = '/';
+                       if (d < 0) {
+                               warn("local: %s", local);
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
+                       }
+                       if (!runique && errno == EACCES &&
+                           chmod(local, 0600) < 0) {
+                               warn("local: %s", local);
+                               (void) signal(SIGINT, oldintr);
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
+                       }
+                       if (runique && errno == EACCES &&
+                          (local = gunique(local)) == NULL) {
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
+                       }
+               }
+               else if (runique && (local = gunique(local)) == NULL) {
+                       (void) signal(SIGINT, oldintr);
+                       code = -1;
+                       return;
+               }
+       }
+       if (!is_retr) {
+               if (curtype != TYPE_A)
+                       changetype(TYPE_A, 0);
+       } else if (curtype != type)
+               changetype(type, 0);
+       if (initconn()) {
+               (void) signal(SIGINT, oldintr);
+               code = -1;
+               return;
+       }
+       if (setjmp(recvabort))
+               goto abort;
+       if (is_retr && restart_point &&
+           command("REST %ld", (long) restart_point) != CONTINUE)
+               return;
+       if (remote) {
+               if (command("%s %s", cmd, remote) != PRELIM) {
+                       (void) signal(SIGINT, oldintr);
+                       return;
+               }
+       } else {
+               if (command("%s", cmd) != PRELIM) {
+                       (void) signal(SIGINT, oldintr);
+                       return;
+               }
+       }
+       din = dataconn("r");
+       if (din == NULL)
+               goto abort;
+       if (strcmp(local, "-") == 0)
+               fout = stdout;
+       else if (*local == '|') {
+               oldintp = signal(SIGPIPE, SIG_IGN);
+               fout = popen(local + 1, "w");
+               if (fout == NULL) {
+                       warn("%s", local+1);
+                       goto abort;
+               }
+               closefunc = pclose;
+       } else {
+               fout = fopen(local, lmode);
+               if (fout == NULL) {
+                       warn("local: %s", local);
+                       goto abort;
+               }
+               closefunc = fclose;
+       }
+       if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
+               st.st_blksize = BUFSIZ;
+       if (st.st_blksize > bufsize) {
+               if (buf)
+                       (void) free(buf);
+               buf = malloc((unsigned)st.st_blksize);
+               if (buf == NULL) {
+                       warn("malloc");
+                       bufsize = 0;
+                       goto abort;
+               }
+               bufsize = st.st_blksize;
+       }
+       (void) gettimeofday(&start, (struct timezone *)0);
+       switch (curtype) {
+
+       case TYPE_I:
+       case TYPE_L:
+               if (restart_point &&
+                   lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
+                       warn("local: %s", local);
+                       if (closefunc != NULL)
+                               (*closefunc)(fout);
+                       return;
+               }
+               errno = d = 0;
+               while ((c = read(fileno(din), buf, bufsize)) > 0) {
+                       if ((d = write(fileno(fout), buf, c)) != c)
+                               break;
+                       bytes += c;
+                       if (hash) {
+                               while (bytes >= hashbytes) {
+                                       (void) putchar('#');
+                                       hashbytes += HASHBYTES;
+                               }
+                               (void) fflush(stdout);
+                       }
+               }
+               if (hash && bytes > 0) {
+                       if (bytes < HASHBYTES)
+                               (void) putchar('#');
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
+               }
+               if (c < 0) {
+                       if (errno != EPIPE)
+                               warn("netin");
+                       bytes = -1;
+               }
+               if (d < c) {
+                       if (d < 0)
+                               warn("local: %s", local);
+                       else
+                               warnx("%s: short write", local);
+               }
+               break;
+
+       case TYPE_A:
+               if (restart_point) {
+                       int i, n, ch;
+
+                       if (fseek(fout, 0L, SEEK_SET) < 0)
+                               goto done;
+                       n = restart_point;
+                       for (i = 0; i++ < n;) {
+                               if ((ch = getc(fout)) == EOF)
+                                       goto done;
+                               if (ch == '\n')
+                                       i++;
+                       }
+                       if (fseek(fout, 0L, SEEK_CUR) < 0) {
+done:
+                               warn("local: %s", local);
+                               if (closefunc != NULL)
+                                       (*closefunc)(fout);
+                               return;
+                       }
+               }
+               while ((c = getc(din)) != EOF) {
+                       if (c == '\n')
+                               bare_lfs++;
+                       while (c == '\r') {
+                               while (hash && (bytes >= hashbytes)) {
+                                       (void) putchar('#');
+                                       (void) fflush(stdout);
+                                       hashbytes += HASHBYTES;
+                               }
+                               bytes++;
+                               if ((c = getc(din)) != '\n' || tcrflag) {
+                                       if (ferror(fout))
+                                               goto break2;
+                                       (void) putc('\r', fout);
+                                       if (c == '\0') {
+                                               bytes++;
+                                               goto contin2;
+                                       }
+                                       if (c == EOF)
+                                               goto contin2;
+                               }
+                       }
+                       (void) putc(c, fout);
+                       bytes++;
+       contin2:        ;
+               }
+break2:
+               if (bare_lfs) {
+                       printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
+                       printf("File may not have transferred correctly.\n");
+               }
+               if (hash) {
+                       if (bytes < hashbytes)
+                               (void) putchar('#');
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
+               }
+               if (ferror(din)) {
+                       if (errno != EPIPE)
+                               warn("netin");
+                       bytes = -1;
+               }
+               if (ferror(fout))
+                       warn("local: %s", local);
+               break;
+       }
+       if (closefunc != NULL)
+               (*closefunc)(fout);
+       (void) signal(SIGINT, oldintr);
+       if (oldintp)
+               (void) signal(SIGPIPE, oldintp);
+       (void) fclose(din);
+       (void) gettimeofday(&stop, (struct timezone *)0);
+       (void) getreply(0);
+       if (bytes > 0 && is_retr)
+               ptransfer("received", bytes, &start, &stop);
+       return;
+abort:
+
+/* abort using RFC959 recommended IP,SYNC sequence  */
+
+       if (oldintp)
+               (void) signal(SIGPIPE, oldintr);
+       (void) signal(SIGINT, SIG_IGN);
+       if (!cpend) {
+               code = -1;
+               (void) signal(SIGINT, oldintr);
+               return;
+       }
+
+       abort_remote(din);
+       code = -1;
+       if (data >= 0) {
+               (void) close(data);
+               data = -1;
+       }
+       if (closefunc != NULL && fout != NULL)
+               (*closefunc)(fout);
+       if (din)
+               (void) fclose(din);
+       (void) gettimeofday(&stop, (struct timezone *)0);
+       if (bytes > 0)
+               ptransfer("received", bytes, &start, &stop);
+       (void) signal(SIGINT, oldintr);
+}
+
+/*
+ * Need to start a listen on the data channel before we send the command,
+ * otherwise the server's connect may fail.
+ */
+int
+initconn()
+{
+       char *p, *a;
+       int result, len, tmpno = 0;
+       int on = 1;
+       int a0, a1, a2, a3, p0, p1;
+
+       if (passivemode) {
+               data = socket(AF_INET, SOCK_STREAM, 0);
+               if (data < 0) {
+                       perror("ftp: socket");
+                       return(1);
+               }
+               if ((options & SO_DEBUG) &&
+                   setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
+                              sizeof (on)) < 0)
+                       perror("ftp: setsockopt (ignored)");
+               if (command("PASV") != COMPLETE) {
+                       printf("Passive mode refused.\n");
+                       goto bad;
+               }
+
+               /*
+                * What we've got at this point is a string of comma
+                * separated one-byte unsigned integer values.
+                * The first four are the an IP address. The fifth is
+                * the MSB of the port number, the sixth is the LSB.
+                * From that we'll prepare a sockaddr_in.
+                */
+
+               if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",
+                          &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
+                       printf("Passive mode address scan failure. "
+                              "Shouldn't happen!\n");
+                       goto bad;
+               }
+
+               bzero(&data_addr, sizeof(data_addr));
+               data_addr.sin_family = AF_INET;
+               a = (char *)&data_addr.sin_addr.s_addr;
+               a[0] = a0 & 0xff;
+               a[1] = a1 & 0xff;
+               a[2] = a2 & 0xff;
+               a[3] = a3 & 0xff;
+               p = (char *)&data_addr.sin_port;
+               p[0] = p0 & 0xff;
+               p[1] = p1 & 0xff;
+
+               if (connect(data, (struct sockaddr *)&data_addr,
+                           sizeof(data_addr)) < 0) {
+                       perror("ftp: connect");
+                       goto bad;
+               }
+#ifdef IP_TOS
+               on = IPTOS_THROUGHPUT;
+               if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
+                              sizeof(int)) < 0)
+                       perror("ftp: setsockopt TOS (ignored)");
+#endif
+               return(0);
+       }
+
+noport:
+       data_addr = myctladdr;
+       if (sendport)
+               data_addr.sin_port = 0; /* let system pick one */ 
+       if (data != -1)
+               (void) close(data);
+       data = socket(AF_INET, SOCK_STREAM, 0);
+       if (data < 0) {
+               warn("socket");
+               if (tmpno)
+                       sendport = 1;
+               return (1);
+       }
+       if (!sendport)
+               if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
+                       warn("setsockopt (reuse address)");
+                       goto bad;
+               }
+       if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
+               warn("bind");
+               goto bad;
+       }
+       if (options & SO_DEBUG &&
+           setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
+               warn("setsockopt (ignored)");
+       len = sizeof (data_addr);
+       if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
+               warn("getsockname");
+               goto bad;
+       }
+       if (listen(data, 1) < 0)
+               warn("listen");
+       if (sendport) {
+               a = (char *)&data_addr.sin_addr;
+               p = (char *)&data_addr.sin_port;
+#define        UC(b)   (((int)b)&0xff)
+               result =
+                   command("PORT %d,%d,%d,%d,%d,%d",
+                     UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
+                     UC(p[0]), UC(p[1]));
+               if (result == ERROR && sendport == -1) {
+                       sendport = 0;
+                       tmpno = 1;
+                       goto noport;
+               }
+               return (result != COMPLETE);
+       }
+       if (tmpno)
+               sendport = 1;
+#ifdef IP_TOS
+       on = IPTOS_THROUGHPUT;
+       if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
+               warn("setsockopt TOS (ignored)");
+#endif
+       return (0);
+bad:
+       (void) close(data), data = -1;
+       if (tmpno)
+               sendport = 1;
+       return (1);
+}
+
+FILE *
+dataconn(lmode)
+       char *lmode;
+{
+       struct sockaddr_in from;
+       int s, fromlen = sizeof (from), tos;
+
+       if (passivemode)
+               return (fdopen(data, lmode));
+
+       s = accept(data, (struct sockaddr *) &from, &fromlen);
+       if (s < 0) {
+               warn("accept");
+               (void) close(data), data = -1;
+               return (NULL);
+       }
+       (void) close(data);
+       data = s;
+#ifdef IP_TOS
+       tos = IPTOS_THROUGHPUT;
+       if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+               warn("setsockopt TOS (ignored)");
+#endif
+       return (fdopen(data, lmode));
+}
+
+void
+ptransfer(direction, bytes, t0, t1)
+       char *direction;
+       long bytes;
+       struct timeval *t0, *t1;
+{
+       struct timeval td;
+       float s;
+       long bs;
+
+       if (verbose) {
+               tvsub(&td, t1, t0);
+               s = td.tv_sec + (td.tv_usec / 1000000.);
+#define        nz(x)   ((x) == 0 ? 1 : (x))
+               bs = bytes / nz(s);
+               printf("%ld bytes %s in %.3g seconds (%ld bytes/s)\n",
+                   bytes, direction, s, bs);
+       }
+}
+
+/*
+void
+tvadd(tsum, t0)
+       struct timeval *tsum, *t0;
+{
+
+       tsum->tv_sec += t0->tv_sec;
+       tsum->tv_usec += t0->tv_usec;
+       if (tsum->tv_usec > 1000000)
+               tsum->tv_sec++, tsum->tv_usec -= 1000000;
+}
+*/
+
+void
+tvsub(tdiff, t1, t0)
+       struct timeval *tdiff, *t1, *t0;
+{
+
+       tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+       tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+       if (tdiff->tv_usec < 0)
+               tdiff->tv_sec--, tdiff->tv_usec += 1000000;
+}
+
+void
+psabort()
+{
+
+       abrtflag++;
+}
+
+void
+pswitch(flag)
+       int flag;
+{
+       sig_t oldintr;
+       static struct comvars {
+               int connect;
+               char name[MAXHOSTNAMELEN];
+               struct sockaddr_in mctl;
+               struct sockaddr_in hctl;
+               FILE *in;
+               FILE *out;
+               int tpe;
+               int curtpe;
+               int cpnd;
+               int sunqe;
+               int runqe;
+               int mcse;
+               int ntflg;
+               char nti[17];
+               char nto[17];
+               int mapflg;
+               char mi[MAXPATHLEN];
+               char mo[MAXPATHLEN];
+       } proxstruct, tmpstruct;
+       struct comvars *ip, *op;
+
+       abrtflag = 0;
+       oldintr = signal(SIGINT, psabort);
+       if (flag) {
+               if (proxy)
+                       return;
+               ip = &tmpstruct;
+               op = &proxstruct;
+               proxy++;
+       } else {
+               if (!proxy)
+                       return;
+               ip = &proxstruct;
+               op = &tmpstruct;
+               proxy = 0;
+       }
+       ip->connect = connected;
+       connected = op->connect;
+       if (hostname) {
+               (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
+               ip->name[strlen(ip->name)] = '\0';
+       } else
+               ip->name[0] = 0;
+       hostname = op->name;
+       ip->hctl = hisctladdr;
+       hisctladdr = op->hctl;
+       ip->mctl = myctladdr;
+       myctladdr = op->mctl;
+       ip->in = cin;
+       cin = op->in;
+       ip->out = cout;
+       cout = op->out;
+       ip->tpe = type;
+       type = op->tpe;
+       ip->curtpe = curtype;
+       curtype = op->curtpe;
+       ip->cpnd = cpend;
+       cpend = op->cpnd;
+       ip->sunqe = sunique;
+       sunique = op->sunqe;
+       ip->runqe = runique;
+       runique = op->runqe;
+       ip->mcse = mcase;
+       mcase = op->mcse;
+       ip->ntflg = ntflag;
+       ntflag = op->ntflg;
+       (void) strncpy(ip->nti, ntin, 16);
+       (ip->nti)[strlen(ip->nti)] = '\0';
+       (void) strcpy(ntin, op->nti);
+       (void) strncpy(ip->nto, ntout, 16);
+       (ip->nto)[strlen(ip->nto)] = '\0';
+       (void) strcpy(ntout, op->nto);
+       ip->mapflg = mapflag;
+       mapflag = op->mapflg;
+       (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
+       (ip->mi)[strlen(ip->mi)] = '\0';
+       (void) strcpy(mapin, op->mi);
+       (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
+       (ip->mo)[strlen(ip->mo)] = '\0';
+       (void) strcpy(mapout, op->mo);
+       (void) signal(SIGINT, oldintr);
+       if (abrtflag) {
+               abrtflag = 0;
+               (*oldintr)(SIGINT);
+       }
+}
+
+void
+abortpt()
+{
+
+       printf("\n");
+       (void) fflush(stdout);
+       ptabflg++;
+       mflag = 0;
+       abrtflag = 0;
+       longjmp(ptabort, 1);
+}
+
+void
+proxtrans(cmd, local, remote)
+       char *cmd, *local, *remote;
+{
+       sig_t oldintr;
+       int secndflag = 0, prox_type, nfnd;
+       char *cmd2;
+       struct fd_set mask;
+
+       if (strcmp(cmd, "RETR"))
+               cmd2 = "RETR";
+       else
+               cmd2 = runique ? "STOU" : "STOR";
+       if ((prox_type = type) == 0) {
+               if (unix_server && unix_proxy)
+                       prox_type = TYPE_I;
+               else
+                       prox_type = TYPE_A;
+       }
+       if (curtype != prox_type)
+               changetype(prox_type, 1);
+       if (command("PASV") != COMPLETE) {
+               printf("proxy server does not support third party transfers.\n");
+               return;
+       }
+       pswitch(0);
+       if (!connected) {
+               printf("No primary connection\n");
+               pswitch(1);
+               code = -1;
+               return;
+       }
+       if (curtype != prox_type)
+               changetype(prox_type, 1);
+       if (command("PORT %s", pasv) != COMPLETE) {
+               pswitch(1);
+               return;
+       }
+       if (setjmp(ptabort))
+               goto abort;
+       oldintr = signal(SIGINT, abortpt);
+       if (command("%s %s", cmd, remote) != PRELIM) {
+               (void) signal(SIGINT, oldintr);
+               pswitch(1);
+               return;
+       }
+       sleep(2);
+       pswitch(1);
+       secndflag++;
+       if (command("%s %s", cmd2, local) != PRELIM)
+               goto abort;
+       ptflag++;
+       (void) getreply(0);
+       pswitch(0);
+       (void) getreply(0);
+       (void) signal(SIGINT, oldintr);
+       pswitch(1);
+       ptflag = 0;
+       printf("local: %s remote: %s\n", local, remote);
+       return;
+abort:
+       (void) signal(SIGINT, SIG_IGN);
+       ptflag = 0;
+       if (strcmp(cmd, "RETR") && !proxy)
+               pswitch(1);
+       else if (!strcmp(cmd, "RETR") && proxy)
+               pswitch(0);
+       if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
+               if (command("%s %s", cmd2, local) != PRELIM) {
+                       pswitch(0);
+                       if (cpend)
+                               abort_remote((FILE *) NULL);
+               }
+               pswitch(1);
+               if (ptabflg)
+                       code = -1;
+               (void) signal(SIGINT, oldintr);
+               return;
+       }
+       if (cpend)
+               abort_remote((FILE *) NULL);
+       pswitch(!proxy);
+       if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
+               if (command("%s %s", cmd2, local) != PRELIM) {
+                       pswitch(0);
+                       if (cpend)
+                               abort_remote((FILE *) NULL);
+                       pswitch(1);
+                       if (ptabflg)
+                               code = -1;
+                       (void) signal(SIGINT, oldintr);
+                       return;
+               }
+       }
+       if (cpend)
+               abort_remote((FILE *) NULL);
+       pswitch(!proxy);
+       if (cpend) {
+               FD_ZERO(&mask);
+               FD_SET(fileno(cin), &mask);
+               if ((nfnd = empty(&mask, 10)) <= 0) {
+                       if (nfnd < 0) {
+                               warn("abort");
+                       }
+                       if (ptabflg)
+                               code = -1;
+                       lostpeer();
+               }
+               (void) getreply(0);
+               (void) getreply(0);
+       }
+       if (proxy)
+               pswitch(0);
+       pswitch(1);
+       if (ptabflg)
+               code = -1;
+       (void) signal(SIGINT, oldintr);
+}
+
+void
+reset(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct fd_set mask;
+       int nfnd = 1;
+
+       FD_ZERO(&mask);
+       while (nfnd > 0) {
+               FD_SET(fileno(cin), &mask);
+               if ((nfnd = empty(&mask,0)) < 0) {
+                       warn("reset");
+                       code = -1;
+                       lostpeer();
+               }
+               else if (nfnd) {
+                       (void) getreply(0);
+               }
+       }
+}
+
+char *
+gunique(local)
+       char *local;
+{
+       static char new[MAXPATHLEN];
+       char *cp = strrchr(local, '/');
+       int d, count=0;
+       char ext = '1';
+
+       if (cp)
+               *cp = '\0';
+       d = access(cp ? local : ".", 2);
+       if (cp)
+               *cp = '/';
+       if (d < 0) {
+               warn("local: %s", local);
+               return ((char *) 0);
+       }
+       (void) strcpy(new, local);
+       cp = new + strlen(new);
+       *cp++ = '.';
+       while (!d) {
+               if (++count == 100) {
+                       printf("runique: can't find unique file name.\n");
+                       return ((char *) 0);
+               }
+               *cp++ = ext;
+               *cp = '\0';
+               if (ext == '9')
+                       ext = '0';
+               else
+                       ext++;
+               if ((d = access(new, 0)) < 0)
+                       break;
+               if (ext != '0')
+                       cp--;
+               else if (*(cp - 2) == '.')
+                       *(cp - 1) = '1';
+               else {
+                       *(cp - 2) = *(cp - 2) + 1;
+                       cp--;
+               }
+       }
+       return (new);
+}
+
+void
+abort_remote(din)
+       FILE *din;
+{
+       char buf[BUFSIZ];
+       int nfnd;
+       struct fd_set mask;
+
+       /*
+        * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
+        * after urgent byte rather than before as is protocol now
+        */
+       sprintf(buf, "%c%c%c", IAC, IP, IAC);
+       if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
+               warn("abort");
+       fprintf(cout,"%cABOR\r\n", DM);
+       (void) fflush(cout);
+       FD_ZERO(&mask);
+       FD_SET(fileno(cin), &mask);
+       if (din) { 
+               FD_SET(fileno(din), &mask);
+       }
+       if ((nfnd = empty(&mask, 10)) <= 0) {
+               if (nfnd < 0) {
+                       warn("abort");
+               }
+               if (ptabflg)
+                       code = -1;
+               lostpeer();
+       }
+       if (din && FD_ISSET(fileno(din), &mask)) {
+               while (read(fileno(din), buf, BUFSIZ) > 0)
+                       /* LOOP */;
+       }
+       if (getreply(0) == ERROR && code == 552) {
+               /* 552 needed for nic style abort */
+               (void) getreply(0);
+       }
+       (void) getreply(0);
+}
diff --git a/ftp.tproj/ftp_var.c b/ftp.tproj/ftp_var.c
new file mode 100644 (file)
index 0000000..f1f972b
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ftp_var.h   8.4 (Berkeley) 10/9/94
+ */
+
+#include <stdio.h>
+
+#include "ftp_var.h"
+
+/*
+ * FTP global variables.
+ */
+
+#include <sys/param.h>
+#include <setjmp.h>
+
+#include "extern.h"
+
+/*
+ * Options and other state info.
+ */
+int    trace;                  /* trace packets exchanged */
+int    hash;                   /* print # for each buffer transferred */
+int    sendport;               /* use PORT cmd for each data connection */
+int    verbose;                /* print messages coming back from server */
+int    connected;              /* connected to server */
+int    fromatty;               /* input is from a terminal */
+int    interactive;            /* interactively prompt on m* cmds */
+int    debug;                  /* debugging level */
+int    bell;                   /* ring bell on cmd completion */
+int    doglob;                 /* glob local file names */
+int    autologin;              /* establish user account on connection */
+int    proxy;                  /* proxy server connection active */
+int    proxflag;               /* proxy connection exists */
+int    sunique;                /* store files on server with unique name */
+int    runique;                /* store local files with unique name */
+int    mcase;                  /* map upper to lower case for mget names */
+int    ntflag;                 /* use ntin ntout tables for name translation */
+int    mapflag;                /* use mapin mapout templates on file names */
+int    code;                   /* return/reply code for ftp command */
+int    crflag;                 /* if 1, strip car. rets. on ascii gets */
+char   pasv[64];               /* passive port for proxy data connection */
+int    passivemode;            /* passive mode enabled */
+char   *altarg;                /* argv[1] with no shell-like preprocessing  */
+char   ntin[17];               /* input translation table */
+char   ntout[17];              /* output translation table */
+char   mapin[MAXPATHLEN];      /* input map template */
+char   mapout[MAXPATHLEN];     /* output map template */
+char   typename[32];           /* name of file transfer type */
+int    type;                   /* requested file transfer type */
+int    curtype;                /* current file transfer type */
+char   structname[32];         /* name of file transfer structure */
+int    stru;                   /* file transfer structure */
+char   formname[32];           /* name of file transfer format */
+int    form;                   /* file transfer format */
+char   modename[32];           /* name of file transfer mode */
+int    mode;                   /* file transfer mode */
+char   bytename[32];           /* local byte size in ascii */
+int    bytesize;               /* local byte size in binary */
+
+char   *hostname;              /* name of host connected to */
+int    unix_server;            /* server is unix, can use binary for ascii */
+int    unix_proxy;             /* proxy is unix, can use binary for ascii */
+
+struct servent *sp;            /* service spec for tcp/ftp */
+
+jmp_buf        toplevel;               /* non-local goto stuff for cmd scanner */
+
+char   line[200];              /* input line buffer */
+char   *stringbase;            /* current scan point in line buffer */
+char   argbuf[200];            /* argument storage buffer */
+char   *argbase;               /* current storage point in arg buffer */
+int    margc;                  /* count of arguments on input line */
+char   *margv[20];             /* args parsed from input line */
+int     cpend;                  /* flag: if != 0, then pending server reply */
+int    mflag;                  /* flag: if != 0, then active multi command */
+
+int    options;                /* used during socket creation */
+
+int macnum;                    /* number of defined macros */
+struct macel macros[16];
+char macbuf[4096];
diff --git a/ftp.tproj/ftp_var.h b/ftp.tproj/ftp_var.h
new file mode 100644 (file)
index 0000000..ad7f790
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ftp_var.h   8.4 (Berkeley) 10/9/94
+ */
+
+/*
+ * FTP global variables.
+ */
+
+#include <sys/param.h>
+#include <setjmp.h>
+
+#include "extern.h"
+
+/*
+ * Options and other state info.
+ */
+extern int     trace;                  /* trace packets exchanged */
+extern int     hash;                   /* pr int # for each buffer transferred */
+extern int     sendport;               /* use PORT cmd for each data connection */
+extern int     verbose;                /* print messages coming back from server */
+extern int     connected;              /* connected to server */
+extern int     fromatty;               /* input is from a terminal */
+extern int     interactive;            /* interactively prompt on m* cmds */
+extern int     debug;                  /* debugging level */
+extern int     bell;                   /* ring bell on cmd completion */
+extern int     doglob;                 /* glob local file names */
+extern int     autologin;              /* establish user account on connection */
+extern int     proxy;                  /* proxy server connection active */
+extern int     proxflag;               /* proxy connection exists */
+extern int     sunique;                /* store files on server with unique name */
+extern int     runique;                /* store local files with unique name */
+extern int     mcase;                  /* map upper to lower case for mget names */
+extern int     ntflag;                 /* use ntin ntout tables for name translation */
+extern int     mapflag;                /* use mapin mapout templates on file names */
+extern int     code;                   /* return/reply code for ftp command */
+extern int     crflag;                 /* if 1, strip car. rets. on ascii gets */
+extern char    pasv[64];               /* passive port for proxy data connection */
+extern int     passivemode;            /* passive mode enabled */
+extern char    *altarg;                /* argv[1] with no shell-like preprocessing  */
+extern char    ntin[17];               /* input translation table */
+extern char    ntout[17];              /* output translation table */
+extern char    mapin[MAXPATHLEN];      /* input map template */
+extern char    mapout[MAXPATHLEN];     /* output map template */
+extern char    typename[32];           /* name of file transfer type */
+extern int     type;                   /* requested file transfer type */
+extern int     curtype;                /* current file transfer type */
+extern char    structname[32];         /* name of file transfer structure */
+extern int     stru;                   /* file transfer structure */
+extern char    formname[32];           /* name of file transfer format */
+extern int     form;                   /* file transfer format */
+extern char    modename[32];           /* name of file transfer mode */
+extern int     mode;                   /* file transfer mode */
+extern char    bytename[32];           /* local byte size in ascii */
+extern int     bytesize;               /* local byte size in binary */
+
+extern char    *hostname;              /* name of host connected to */
+extern int     unix_server;            /* server is unix, can use binary for ascii */
+extern int     unix_proxy;             /* proxy is unix, can use binary for ascii */
+
+extern struct  servent *sp;            /* service spec for tcp/ftp */
+
+extern jmp_buf toplevel;               /* non-local goto stuff for cmd scanner */
+
+extern char    line[200];              /* input line buffer */
+extern char    *stringbase;            /* current scan point in line buffer */
+extern char    argbuf[200];            /* argument storage buffer */
+extern char    *argbase;               /* current storage point in arg buffer */
+extern int     margc;                  /* count of arguments on input line */
+extern char    *margv[20];             /* args parsed from input line */
+extern int     cpend;                  /* flag: if != 0, then pending server reply */
+extern int     mflag;                  /* flag: if != 0, then active multi command */
+
+extern int     options;                /* used during socket creation */
+
+/*
+ * Format of command table.
+ */
+struct cmd {
+       char    *c_name;        /* name of command */
+       char    *c_help;        /* help string */
+       char    c_bell;         /* give bell when command completes */
+       char    c_conn;         /* must be connected to use command */
+       char    c_proxy;        /* proxy server may execute */
+       void    (*c_handler) __P((int, char **)); /* function to call */
+};
+
+struct macel {
+       char mac_name[9];       /* macro name */
+       char *mac_start;        /* start of macro in macbuf */
+       char *mac_end;          /* end of macro in macbuf */
+};
+
+extern int macnum;                     /* number of defined macros */
+extern struct macel macros[16];
+extern char macbuf[4096];
diff --git a/ftp.tproj/h.template b/ftp.tproj/h.template
new file mode 100644 (file)
index 0000000..f3c1b04
--- /dev/null
@@ -0,0 +1,11 @@
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
diff --git a/ftp.tproj/m.template b/ftp.tproj/m.template
new file mode 100644 (file)
index 0000000..1216fe5
--- /dev/null
@@ -0,0 +1,18 @@
+$$ Lines starting with $$ are not inserted into newly created files
+$$ The following substitutions are made:
+$$
+$$ $FILENAME$                e.g. foo.m
+$$ $FILENAMESANSEXTENSION$   e.g. foo
+$$ $DIRECTORY$               e.g. /tmp/MyNewApp
+$$ $PROJECTNAME$             e.g. MyNewApp
+$$ $SUBPROJECTNAME$          e.g. TheGoodPart.subproj
+$$ $USERNAME$                e.g. mwagner
+$$ $DATE$                    e.g. Jan-1-1994
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import "$FILENAMESANSEXTENSION$.h"
+
+@implementation $FILENAMESANSEXTENSION$
+
+@end
diff --git a/ftp.tproj/main.c b/ftp.tproj/main.c
new file mode 100644 (file)
index 0000000..4ad3ed2
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * FTP User Program -- Command Interface.
+ */
+/*#include <sys/ioctl.h>*/
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/ftp.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ftp_var.h"
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int ch, top;
+       struct passwd *pw = NULL;
+       char *cp, homedir[MAXPATHLEN];
+
+       sp = getservbyname("ftp", "tcp");
+       if (sp == 0)
+               errx(1, "ftp/tcp: unknown service");
+       doglob = 1;
+       interactive = 1;
+       autologin = 1;
+
+       while ((ch = getopt(argc, argv, "dgintv")) != EOF) {
+               switch (ch) {
+               case 'd':
+                       options |= SO_DEBUG;
+                       debug++;
+                       break;
+                       
+               case 'g':
+                       doglob = 0;
+                       break;
+
+               case 'i':
+                       interactive = 0;
+                       break;
+
+               case 'n':
+                       autologin = 0;
+                       break;
+
+               case 't':
+                       trace++;
+                       break;
+
+               case 'v':
+                       verbose++;
+                       break;
+
+               default:
+                       (void)fprintf(stderr,
+                               "usage: ftp [-dgintv] [host [port]]\n");
+                       exit(1);
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       fromatty = isatty(fileno(stdin));
+       if (fromatty)
+               verbose++;
+       cpend = 0;      /* no pending replies */
+       proxy = 0;      /* proxy not active */
+       passivemode = 0; /* passive mode not active */
+       crflag = 1;     /* strip c.r. on ascii gets */
+       sendport = -1;  /* not using ports */
+       /*
+        * Set up the home directory in case we're globbing.
+        */
+       cp = getlogin();
+       if (cp != NULL) {
+               pw = getpwnam(cp);
+       }
+       if (pw == NULL)
+               pw = getpwuid(getuid());
+       if (pw != NULL) {
+               home = homedir;
+               (void) strcpy(home, pw->pw_dir);
+       }
+       if (argc > 0) {
+               char *xargv[5];
+               extern char *__progname;
+
+               if (setjmp(toplevel))
+                       exit(0);
+               (void) signal(SIGINT, intr);
+               (void) signal(SIGPIPE, lostpeer);
+               xargv[0] = __progname;
+               xargv[1] = argv[0];
+               xargv[2] = argv[1];
+               xargv[3] = argv[2];
+               xargv[4] = NULL;
+               setpeer(argc+1, xargv);
+       }
+       top = setjmp(toplevel) == 0;
+       if (top) {
+               (void) signal(SIGINT, intr);
+               (void) signal(SIGPIPE, lostpeer);
+       }
+       for (;;) {
+               cmdscanner(top);
+               top = 1;
+       }
+}
+
+void
+intr()
+{
+
+       longjmp(toplevel, 1);
+}
+
+void
+lostpeer()
+{
+
+       if (connected) {
+               if (cout != NULL) {
+                       (void) shutdown(fileno(cout), 1+1);
+                       (void) fclose(cout);
+                       cout = NULL;
+               }
+               if (data >= 0) {
+                       (void) shutdown(data, 1+1);
+                       (void) close(data);
+                       data = -1;
+               }
+               connected = 0;
+       }
+       pswitch(1);
+       if (connected) {
+               if (cout != NULL) {
+                       (void) shutdown(fileno(cout), 1+1);
+                       (void) fclose(cout);
+                       cout = NULL;
+               }
+               connected = 0;
+       }
+       proxflag = 0;
+       pswitch(0);
+}
+
+/*
+char *
+tail(filename)
+       char *filename;
+{
+       char *s;
+       
+       while (*filename) {
+               s = strrchr(filename, '/');
+               if (s == NULL)
+                       break;
+               if (s[1])
+                       return (s + 1);
+               *s = '\0';
+       }
+       return (filename);
+}
+*/
+
+/*
+ * Command parser.
+ */
+void
+cmdscanner(top)
+       int top;
+{
+       struct cmd *c;
+       int l;
+
+       if (!top)
+               (void) putchar('\n');
+       for (;;) {
+               if (fromatty) {
+                       printf("ftp> ");
+                       (void) fflush(stdout);
+               }
+               if (fgets(line, sizeof line, stdin) == NULL)
+                       quit(0, 0);
+               l = strlen(line);
+               if (l == 0)
+                       break;
+               if (line[--l] == '\n') {
+                       if (l == 0)
+                               break;
+                       line[l] = '\0';
+               } else if (l == sizeof(line) - 2) {
+                       printf("sorry, input line too long\n");
+                       while ((l = getchar()) != '\n' && l != EOF)
+                               /* void */;
+                       break;
+               } /* else it was a line without a newline */
+               makeargv();
+               if (margc == 0) {
+                       continue;
+               }
+               c = getcmd(margv[0]);
+               if (c == (struct cmd *)-1) {
+                       printf("?Ambiguous command\n");
+                       continue;
+               }
+               if (c == 0) {
+                       printf("?Invalid command\n");
+                       continue;
+               }
+               if (c->c_conn && !connected) {
+                       printf("Not connected.\n");
+                       continue;
+               }
+               (*c->c_handler)(margc, margv);
+               if (bell && c->c_bell)
+                       (void) putchar('\007');
+               if (c->c_handler != help)
+                       break;
+       }
+       (void) signal(SIGINT, intr);
+       (void) signal(SIGPIPE, lostpeer);
+}
+
+struct cmd *
+getcmd(name)
+       char *name;
+{
+       char *p, *q;
+       struct cmd *c, *found;
+       int nmatches, longest;
+
+       longest = 0;
+       nmatches = 0;
+       found = 0;
+       for (c = cmdtab; p = c->c_name; c++) {
+               for (q = name; *q == *p++; q++)
+                       if (*q == 0)            /* exact match? */
+                               return (c);
+               if (!*q) {                      /* the name was a prefix */
+                       if (q - name > longest) {
+                               longest = q - name;
+                               nmatches = 1;
+                               found = c;
+                       } else if (q - name == longest)
+                               nmatches++;
+               }
+       }
+       if (nmatches > 1)
+               return ((struct cmd *)-1);
+       return (found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+
+int slrflag;
+
+void
+makeargv()
+{
+       char **argp;
+
+       margc = 0;
+       argp = margv;
+       stringbase = line;              /* scan from first of buffer */
+       argbase = argbuf;               /* store from first of buffer */
+       slrflag = 0;
+       while (*argp++ = slurpstring())
+               margc++;
+}
+
+/*
+ * Parse string into argbuf;
+ * implemented with FSM to
+ * handle quoting and strings
+ */
+char *
+slurpstring()
+{
+       int got_one = 0;
+       char *sb = stringbase;
+       char *ap = argbase;
+       char *tmp = argbase;            /* will return this if token found */
+
+       if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
+               switch (slrflag) {      /* and $ as token for macro invoke */
+                       case 0:
+                               slrflag++;
+                               stringbase++;
+                               return ((*sb == '!') ? "!" : "$");
+                               /* NOTREACHED */
+                       case 1:
+                               slrflag++;
+                               altarg = stringbase;
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+S0:
+       switch (*sb) {
+
+       case '\0':
+               goto OUT;
+
+       case ' ':
+       case '\t':
+               sb++; goto S0;
+
+       default:
+               switch (slrflag) {
+                       case 0:
+                               slrflag++;
+                               break;
+                       case 1:
+                               slrflag++;
+                               altarg = sb;
+                               break;
+                       default:
+                               break;
+               }
+               goto S1;
+       }
+
+S1:
+       switch (*sb) {
+
+       case ' ':
+       case '\t':
+       case '\0':
+               goto OUT;       /* end of token */
+
+       case '\\':
+               sb++; goto S2;  /* slurp next character */
+
+       case '"':
+               sb++; goto S3;  /* slurp quoted string */
+
+       default:
+               *ap++ = *sb++;  /* add character to token */
+               got_one = 1;
+               goto S1;
+       }
+
+S2:
+       switch (*sb) {
+
+       case '\0':
+               goto OUT;
+
+       default:
+               *ap++ = *sb++;
+               got_one = 1;
+               goto S1;
+       }
+
+S3:
+       switch (*sb) {
+
+       case '\0':
+               goto OUT;
+
+       case '"':
+               sb++; goto S1;
+
+       default:
+               *ap++ = *sb++;
+               got_one = 1;
+               goto S3;
+       }
+
+OUT:
+       if (got_one)
+               *ap++ = '\0';
+       argbase = ap;                   /* update storage pointer */
+       stringbase = sb;                /* update scan pointer */
+       if (got_one) {
+               return (tmp);
+       }
+       switch (slrflag) {
+               case 0:
+                       slrflag++;
+                       break;
+               case 1:
+                       slrflag++;
+                       altarg = (char *) 0;
+                       break;
+               default:
+                       break;
+       }
+       return ((char *)0);
+}
+
+#define HELPINDENT ((int) sizeof ("directory"))
+
+/*
+ * Help command.
+ * Call each command handler with argc == 0 and argv[0] == name.
+ */
+void
+help(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct cmd *c;
+
+       if (argc == 1) {
+               int i, j, w, k;
+               int columns, width = 0, lines;
+
+               printf("Commands may be abbreviated.  Commands are:\n\n");
+               for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+                       int len = strlen(c->c_name);
+
+                       if (len > width)
+                               width = len;
+               }
+               width = (width + 8) &~ 7;
+               columns = 80 / width;
+               if (columns == 0)
+                       columns = 1;
+               lines = (NCMDS + columns - 1) / columns;
+               for (i = 0; i < lines; i++) {
+                       for (j = 0; j < columns; j++) {
+                               c = cmdtab + j * lines + i;
+                               if (c->c_name && (!proxy || c->c_proxy)) {
+                                       printf("%s", c->c_name);
+                               }
+                               else if (c->c_name) {
+                                       for (k=0; k < strlen(c->c_name); k++) {
+                                               (void) putchar(' ');
+                                       }
+                               }
+                               if (c + lines >= &cmdtab[NCMDS]) {
+                                       printf("\n");
+                                       break;
+                               }
+                               w = strlen(c->c_name);
+                               while (w < width) {
+                                       w = (w + 8) &~ 7;
+                                       (void) putchar('\t');
+                               }
+                       }
+               }
+               return;
+       }
+       while (--argc > 0) {
+               char *arg;
+               arg = *++argv;
+               c = getcmd(arg);
+               if (c == (struct cmd *)-1)
+                       printf("?Ambiguous help command %s\n", arg);
+               else if (c == (struct cmd *)0)
+                       printf("?Invalid help command %s\n", arg);
+               else
+                       printf("%-*s\t%s\n", HELPINDENT,
+                               c->c_name, c->c_help);
+       }
+}
diff --git a/ftp.tproj/pathnames.h b/ftp.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..4403aa8
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#undef _PATH_TMP
+#define        _PATH_TMP       "/tmp/ftpXXXXXX"
diff --git a/ftp.tproj/ruserpass.c b/ftp.tproj/ruserpass.c
new file mode 100644 (file)
index 0000000..ed5a406
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ftp_var.h"
+
+static int token __P((void));
+static FILE *cfile;
+
+#define        DEFAULT 1
+#define        LOGIN   2
+#define        PASSWD  3
+#define        ACCOUNT 4
+#define MACDEF  5
+#define        ID      10
+#define        MACH    11
+
+static char tokval[100];
+
+static struct toktab {
+       char *tokstr;
+       int tval;
+} toktab[]= {
+       { "default",    DEFAULT },
+       { "login",      LOGIN },
+       { "password",   PASSWD },
+       { "passwd",     PASSWD },
+       { "account",    ACCOUNT },
+       { "machine",    MACH },
+       { "macdef",     MACDEF },
+       { NULL,         0 }
+};
+
+int
+ruserpass(host, aname, apass, aacct)
+       char *host, **aname, **apass, **aacct;
+{
+       char *hdir, buf[BUFSIZ], *tmp;
+       char myname[MAXHOSTNAMELEN], *mydomain;
+       int t, i, c, usedefault = 0;
+       struct stat stb;
+
+       hdir = getenv("HOME");
+       if (hdir == NULL)
+               hdir = ".";
+       (void) sprintf(buf, "%s/.netrc", hdir);
+       cfile = fopen(buf, "r");
+       if (cfile == NULL) {
+               if (errno != ENOENT)
+                       warn("%s", buf);
+               return (0);
+       }
+       if (gethostname(myname, sizeof(myname)) < 0)
+               myname[0] = '\0';
+       if ((mydomain = strchr(myname, '.')) == NULL)
+               mydomain = "";
+next:
+       while ((t = token())) switch(t) {
+
+       case DEFAULT:
+               usedefault = 1;
+               /* FALL THROUGH */
+
+       case MACH:
+               if (!usedefault) {
+                       if (token() != ID)
+                               continue;
+                       /*
+                        * Allow match either for user's input host name
+                        * or official hostname.  Also allow match of 
+                        * incompletely-specified host in local domain.
+                        */
+                       if (strcasecmp(host, tokval) == 0)
+                               goto match;
+                       if (strcasecmp(hostname, tokval) == 0)
+                               goto match;
+                       if ((tmp = strchr(hostname, '.')) != NULL &&
+                           strcasecmp(tmp, mydomain) == 0 &&
+                           strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
+                           tokval[tmp - hostname] == '\0')
+                               goto match;
+                       if ((tmp = strchr(host, '.')) != NULL &&
+                           strcasecmp(tmp, mydomain) == 0 &&
+                           strncasecmp(host, tokval, tmp - host) == 0 &&
+                           tokval[tmp - host] == '\0')
+                               goto match;
+                       continue;
+               }
+       match:
+               while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
+
+               case LOGIN:
+                       if (token())
+                               if (*aname == 0) { 
+                                       *aname = malloc((unsigned) strlen(tokval) + 1);
+                                       (void) strcpy(*aname, tokval);
+                               } else {
+                                       if (strcmp(*aname, tokval))
+                                               goto next;
+                               }
+                       break;
+               case PASSWD:
+                       if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
+                           fstat(fileno(cfile), &stb) >= 0 &&
+                           (stb.st_mode & 077) != 0) {
+       warnx("Error: .netrc file is readable by others.");
+       warnx("Remove password or make file unreadable by others.");
+                               goto bad;
+                       }
+                       if (token() && *apass == 0) {
+                               *apass = malloc((unsigned) strlen(tokval) + 1);
+                               (void) strcpy(*apass, tokval);
+                       }
+                       break;
+               case ACCOUNT:
+                       if (fstat(fileno(cfile), &stb) >= 0
+                           && (stb.st_mode & 077) != 0) {
+       warnx("Error: .netrc file is readable by others.");
+       warnx("Remove account or make file unreadable by others.");
+                               goto bad;
+                       }
+                       if (token() && *aacct == 0) {
+                               *aacct = malloc((unsigned) strlen(tokval) + 1);
+                               (void) strcpy(*aacct, tokval);
+                       }
+                       break;
+               case MACDEF:
+                       if (proxy) {
+                               (void) fclose(cfile);
+                               return (0);
+                       }
+                       while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t');
+                       if (c == EOF || c == '\n') {
+                               printf("Missing macdef name argument.\n");
+                               goto bad;
+                       }
+                       if (macnum == 16) {
+                               printf("Limit of 16 macros have already been defined\n");
+                               goto bad;
+                       }
+                       tmp = macros[macnum].mac_name;
+                       *tmp++ = c;
+                       for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
+                           !isspace(c); ++i) {
+                               *tmp++ = c;
+                       }
+                       if (c == EOF) {
+                               printf("Macro definition missing null line terminator.\n");
+                               goto bad;
+                       }
+                       *tmp = '\0';
+                       if (c != '\n') {
+                               while ((c=getc(cfile)) != EOF && c != '\n');
+                       }
+                       if (c == EOF) {
+                               printf("Macro definition missing null line terminator.\n");
+                               goto bad;
+                       }
+                       if (macnum == 0) {
+                               macros[macnum].mac_start = macbuf;
+                       }
+                       else {
+                               macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
+                       }
+                       tmp = macros[macnum].mac_start;
+                       while (tmp != macbuf + 4096) {
+                               if ((c=getc(cfile)) == EOF) {
+                               printf("Macro definition missing null line terminator.\n");
+                                       goto bad;
+                               }
+                               *tmp = c;
+                               if (*tmp == '\n') {
+                                       if (*(tmp-1) == '\0') {
+                                          macros[macnum++].mac_end = tmp - 1;
+                                          break;
+                                       }
+                                       *tmp = '\0';
+                               }
+                               tmp++;
+                       }
+                       if (tmp == macbuf + 4096) {
+                               printf("4K macro buffer exceeded\n");
+                               goto bad;
+                       }
+                       break;
+               default:
+                       warnx("Unknown .netrc keyword %s", tokval);
+                       break;
+               }
+               goto done;
+       }
+done:
+       (void) fclose(cfile);
+       return (0);
+bad:
+       (void) fclose(cfile);
+       return (-1);
+}
+
+static int
+token()
+{
+       char *cp;
+       int c;
+       struct toktab *t;
+
+       if (feof(cfile) || ferror(cfile))
+               return (0);
+       while ((c = getc(cfile)) != EOF &&
+           (c == '\n' || c == '\t' || c == ' ' || c == ','))
+               continue;
+       if (c == EOF)
+               return (0);
+       cp = tokval;
+       if (c == '"') {
+               while ((c = getc(cfile)) != EOF && c != '"') {
+                       if (c == '\\')
+                               c = getc(cfile);
+                       *cp++ = c;
+               }
+       } else {
+               *cp++ = c;
+               while ((c = getc(cfile)) != EOF
+                   && c != '\n' && c != '\t' && c != ' ' && c != ',') {
+                       if (c == '\\')
+                               c = getc(cfile);
+                       *cp++ = c;
+               }
+       }
+       *cp = 0;
+       if (tokval[0] == 0)
+               return (0);
+       for (t = toktab; t->tokstr; t++)
+               if (!strcmp(t->tokstr, tokval))
+                       return (t->tval);
+       return (ID);
+}
diff --git a/ftpd.tproj/Makefile b/ftpd.tproj/Makefile
new file mode 100644 (file)
index 0000000..a1d09f3
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ftpd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h pathnames.h
+
+OTHERLINKED = ftpcmd.y
+
+CFILES = ftpd.c logwtmp.c popen.c vers.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble ftpd.8
+
+OTHERLINKEDOFILES = ftpcmd.o
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ftpd.tproj/Makefile.postamble b/ftpd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7ede358
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
diff --git a/ftpd.tproj/Makefile.preamble b/ftpd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dcbd1c8
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
diff --git a/ftpd.tproj/PB.project b/ftpd.tproj/PB.project
new file mode 100644 (file)
index 0000000..b135f93
--- /dev/null
@@ -0,0 +1,40 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (extern.h, pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (ftpcmd.y, ftpd.c, logwtmp.c, popen.c, vers.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, ftpd.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ftpd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ftpd.tproj/extern.h b/ftpd.tproj/extern.h
new file mode 100644 (file)
index 0000000..1d02d54
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)extern.h    8.2 (Berkeley) 4/4/94
+ */
+
+void   blkfree __P((char **));
+char  **copyblk __P((char **));
+void   cwd __P((char *));
+void   delete __P((char *));
+void   dologout __P((int));
+void   fatal __P((char *));
+int    ftpd_pclose __P((FILE *));
+FILE   *ftpd_popen __P((char *, char *));
+char   *getline __P((char *, int, FILE *));
+void   logwtmp __P((char *, char *, char *));
+void   lreply __P((int, const char *, ...));
+void   makedir __P((char *));
+void   nack __P((char *));
+void   pass __P((char *));
+void   passive __P((void));
+void   perror_reply __P((int, char *));
+void   pwd __P((void));
+void   removedir __P((char *));
+void   renamecmd __P((char *, char *));
+char   *renamefrom __P((char *));
+void   reply __P((int, const char *, ...));
+void   retrieve __P((char *, char *));
+void   send_file_list __P((char *));
+void   setproctitle __P((const char *, ...));
+void   statcmd __P((void));
+void   statfilecmd __P((char *));
+void   store __P((char *, char *, int));
+void   upper __P((char *));
+void   user __P((char *));
+void   yyerror __P((char *));
diff --git a/ftpd.tproj/ftpcmd.y b/ftpd.tproj/ftpcmd.y
new file mode 100644 (file)
index 0000000..aeb59bd
--- /dev/null
@@ -0,0 +1,1269 @@
+/*
+ * Copyright (c) 1985, 1988, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ftpcmd.y    8.3 (Berkeley) 4/6/94
+ */
+
+/*
+ * Grammar for FTP commands.
+ * See RFC 959.
+ */
+
+%{
+
+#ifndef lint
+static char sccsid[] = "@(#)ftpcmd.y   8.3 (Berkeley) 4/6/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/ftp.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <glob.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+extern struct sockaddr_in data_dest;
+extern int logged_in;
+extern struct passwd *pw;
+extern int guest;
+extern int logging;
+extern int type;
+extern int form;
+extern int debug;
+extern int timeout;
+extern int maxtimeout;
+extern  int pdata;
+extern char hostname[], remotehost[];
+extern char proctitle[];
+extern int usedefault;
+extern  int transflag;
+extern  char tmpline[];
+
+off_t  restart_point;
+
+static int cmd_type;
+static int cmd_form;
+static int cmd_bytesz;
+char   cbuf[512];
+char   *fromname;
+
+%}
+
+%union {
+       int     i;
+       char   *s;
+}
+
+%token
+       A       B       C       E       F       I
+       L       N       P       R       S       T
+
+       SP      CRLF    COMMA
+
+       USER    PASS    ACCT    REIN    QUIT    PORT
+       PASV    TYPE    STRU    MODE    RETR    STOR
+       APPE    MLFL    MAIL    MSND    MSOM    MSAM
+       MRSQ    MRCP    ALLO    REST    RNFR    RNTO
+       ABOR    DELE    CWD     LIST    NLST    SITE
+       STAT    HELP    NOOP    MKD     RMD     PWD
+       CDUP    STOU    SMNT    SYST    SIZE    MDTM
+
+       UMASK   IDLE    CHMOD
+
+       LEXERR
+
+%token <s> STRING
+%token <i> NUMBER
+
+%type  <i> check_login octal_number byte_size
+%type  <i> struct_code mode_code type_code form_code
+%type  <s> pathstring pathname password username
+
+%start cmd_list
+
+%%
+
+cmd_list
+       : /* empty */
+       | cmd_list cmd
+               {
+                       fromname = (char *) 0;
+                       restart_point = (off_t) 0;
+               }
+       | cmd_list rcmd
+       ;
+
+cmd
+       : USER SP username CRLF
+               {
+                       user($3);
+                       free($3);
+               }
+       | PASS SP password CRLF
+               {
+                       pass($3);
+                       free($3);
+               }
+       | PORT SP host_port CRLF
+               {
+                       usedefault = 0;
+                       if (pdata >= 0) {
+                               (void) close(pdata);
+                               pdata = -1;
+                       }
+                       reply(200, "PORT command successful.");
+               }
+       | PASV CRLF
+               {
+                       passive();
+               }
+       | TYPE SP type_code CRLF
+               {
+                       switch (cmd_type) {
+
+                       case TYPE_A:
+                               if (cmd_form == FORM_N) {
+                                       reply(200, "Type set to A.");
+                                       type = cmd_type;
+                                       form = cmd_form;
+                               } else
+                                       reply(504, "Form must be N.");
+                               break;
+
+                       case TYPE_E:
+                               reply(504, "Type E not implemented.");
+                               break;
+
+                       case TYPE_I:
+                               reply(200, "Type set to I.");
+                               type = cmd_type;
+                               break;
+
+                       case TYPE_L:
+#if NBBY == 8
+                               if (cmd_bytesz == 8) {
+                                       reply(200,
+                                           "Type set to L (byte size 8).");
+                                       type = cmd_type;
+                               } else
+                                       reply(504, "Byte size must be 8.");
+#else /* NBBY == 8 */
+                               UNIMPLEMENTED for NBBY != 8
+#endif /* NBBY == 8 */
+                       }
+               }
+       | STRU SP struct_code CRLF
+               {
+                       switch ($3) {
+
+                       case STRU_F:
+                               reply(200, "STRU F ok.");
+                               break;
+
+                       default:
+                               reply(504, "Unimplemented STRU type.");
+                       }
+               }
+       | MODE SP mode_code CRLF
+               {
+                       switch ($3) {
+
+                       case MODE_S:
+                               reply(200, "MODE S ok.");
+                               break;
+
+                       default:
+                               reply(502, "Unimplemented MODE type.");
+                       }
+               }
+       | ALLO SP NUMBER CRLF
+               {
+                       reply(202, "ALLO command ignored.");
+               }
+       | ALLO SP NUMBER SP R SP NUMBER CRLF
+               {
+                       reply(202, "ALLO command ignored.");
+               }
+       | RETR check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               retrieve((char *) 0, $4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | STOR check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               store($4, "w", 0);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | APPE check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               store($4, "a", 0);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | NLST check_login CRLF
+               {
+                       if ($2)
+                               send_file_list(".");
+               }
+       | NLST check_login SP STRING CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               send_file_list($4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | LIST check_login CRLF
+               {
+                       if ($2)
+                               retrieve("/bin/ls -lgA", "");
+               }
+       | LIST check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               retrieve("/bin/ls -lgA %s", $4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | STAT check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               statfilecmd($4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | STAT CRLF
+               {
+                       statcmd();
+               }
+       | DELE check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               delete($4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | RNTO SP pathname CRLF
+               {
+                       if (fromname) {
+                               renamecmd(fromname, $3);
+                               free(fromname);
+                               fromname = (char *) 0;
+                       } else {
+                               reply(503, "Bad sequence of commands.");
+                       }
+                       free($3);
+               }
+       | ABOR CRLF
+               {
+                       reply(225, "ABOR command successful.");
+               }
+       | CWD check_login CRLF
+               {
+                       if ($2)
+                               cwd(pw->pw_dir);
+               }
+       | CWD check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               cwd($4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | HELP CRLF
+               {
+                       help(cmdtab, (char *) 0);
+               }
+       | HELP SP STRING CRLF
+               {
+                       char *cp = $3;
+
+                       if (strncasecmp(cp, "SITE", 4) == 0) {
+                               cp = $3 + 4;
+                               if (*cp == ' ')
+                                       cp++;
+                               if (*cp)
+                                       help(sitetab, cp);
+                               else
+                                       help(sitetab, (char *) 0);
+                       } else
+                               help(cmdtab, $3);
+               }
+       | NOOP CRLF
+               {
+                       reply(200, "NOOP command successful.");
+               }
+       | MKD check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               makedir($4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | RMD check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               removedir($4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | PWD check_login CRLF
+               {
+                       if ($2)
+                               pwd();
+               }
+       | CDUP check_login CRLF
+               {
+                       if ($2)
+                               cwd("..");
+               }
+       | SITE SP HELP CRLF
+               {
+                       help(sitetab, (char *) 0);
+               }
+       | SITE SP HELP SP STRING CRLF
+               {
+                       help(sitetab, $5);
+               }
+       | SITE SP UMASK check_login CRLF
+               {
+                       int oldmask;
+
+                       if ($4) {
+                               oldmask = umask(0);
+                               (void) umask(oldmask);
+                               reply(200, "Current UMASK is %03o", oldmask);
+                       }
+               }
+       | SITE SP UMASK check_login SP octal_number CRLF
+               {
+                       int oldmask;
+
+                       if ($4) {
+                               if (($6 == -1) || ($6 > 0777)) {
+                                       reply(501, "Bad UMASK value");
+                               } else {
+                                       oldmask = umask($6);
+                                       reply(200,
+                                           "UMASK set to %03o (was %03o)",
+                                           $6, oldmask);
+                               }
+                       }
+               }
+       | SITE SP CHMOD check_login SP octal_number SP pathname CRLF
+               {
+                       if ($4 && ($8 != NULL)) {
+                               if ($6 > 0777)
+                                       reply(501,
+                               "CHMOD: Mode value must be between 0 and 0777");
+                               else if (chmod($8, $6) < 0)
+                                       perror_reply(550, $8);
+                               else
+                                       reply(200, "CHMOD command successful.");
+                       }
+                       if ($8 != NULL)
+                               free($8);
+               }
+       | SITE SP IDLE CRLF
+               {
+                       reply(200,
+                           "Current IDLE time limit is %d seconds; max %d",
+                               timeout, maxtimeout);
+               }
+       | SITE SP IDLE SP NUMBER CRLF
+               {
+                       if ($5 < 30 || $5 > maxtimeout) {
+                               reply(501,
+                       "Maximum IDLE time must be between 30 and %d seconds",
+                                   maxtimeout);
+                       } else {
+                               timeout = $5;
+                               (void) alarm((unsigned) timeout);
+                               reply(200,
+                                   "Maximum IDLE time set to %d seconds",
+                                   timeout);
+                       }
+               }
+       | STOU check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               store($4, "w", 1);
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | SYST CRLF
+               {
+#ifdef __APPLE__
+                       reply(215, "BSD Type: L%d", NBBY);
+#else
+#if defined(unix)
+#ifdef BSD
+                       reply(215, "UNIX Type: L%d Version: BSD-%d", NBBY, BSD);
+#else /* BSD */
+                       reply(215, "UNIX Type: L%d", NBBY);
+#endif /* BSD */
+#else /* unix */
+                       reply(215, "UNKNOWN Type: L%d", NBBY);
+#endif /* unix */
+#endif /* __APPLE__ */
+               }
+
+               /*
+                * SIZE is not in RFC959, but Postel has blessed it and
+                * it will be in the updated RFC.
+                *
+                * Return size of file in a format suitable for
+                * using with RESTART (we just count bytes).
+                */
+       | SIZE check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL)
+                               sizecmd($4);
+                       if ($4 != NULL)
+                               free($4);
+               }
+
+               /*
+                * MDTM is not in RFC959, but Postel has blessed it and
+                * it will be in the updated RFC.
+                *
+                * Return modification time of file as an ISO 3307
+                * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx
+                * where xxx is the fractional second (of any precision,
+                * not necessarily 3 digits)
+                */
+       | MDTM check_login SP pathname CRLF
+               {
+                       if ($2 && $4 != NULL) {
+                               struct stat stbuf;
+                               if (stat($4, &stbuf) < 0)
+                                       reply(550, "%s: %s",
+                                           $4, strerror(errno));
+                               else if (!S_ISREG(stbuf.st_mode)) {
+                                       reply(550, "%s: not a plain file.", $4);
+                               } else {
+                                       struct tm *t;
+                                       t = gmtime(&stbuf.st_mtime);
+                                       reply(213,
+                                           "%04d%02d%02d%02d%02d%02d",
+                                           1900+t->tm_year, t->tm_mon+1, t->tm_mday,
+                                           t->tm_hour, t->tm_min, t->tm_sec);
+                               }
+                       }
+                       if ($4 != NULL)
+                               free($4);
+               }
+       | QUIT CRLF
+               {
+                       reply(221, "Goodbye.");
+                       dologout(0);
+               }
+       | error CRLF
+               {
+                       yyerrok;
+               }
+       ;
+rcmd
+       : RNFR check_login SP pathname CRLF
+               {
+                       char *renamefrom();
+
+                       restart_point = (off_t) 0;
+                       if ($2 && $4) {
+                               fromname = renamefrom($4);
+                               if (fromname == (char *) 0 && $4) {
+                                       free($4);
+                               }
+                       }
+               }
+       | REST SP byte_size CRLF
+               {
+                       fromname = (char *) 0;
+                       restart_point = $3;     /* XXX $3 is only "int" */
+                       reply(350, "Restarting at %qd. %s", restart_point,
+                           "Send STORE or RETRIEVE to initiate transfer.");
+               }
+       ;
+
+username
+       : STRING
+       ;
+
+password
+       : /* empty */
+               {
+                       $$ = (char *)calloc(1, sizeof(char));
+               }
+       | STRING
+       ;
+
+byte_size
+       : NUMBER
+       ;
+
+host_port
+       : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA
+               NUMBER COMMA NUMBER
+               {
+                       char *a, *p;
+
+                       a = (char *)&data_dest.sin_addr;
+                       a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7;
+                       p = (char *)&data_dest.sin_port;
+                       p[0] = $9; p[1] = $11;
+                       data_dest.sin_family = AF_INET;
+               }
+       ;
+
+form_code
+       : N
+               {
+                       $$ = FORM_N;
+               }
+       | T
+               {
+                       $$ = FORM_T;
+               }
+       | C
+               {
+                       $$ = FORM_C;
+               }
+       ;
+
+type_code
+       : A
+               {
+                       cmd_type = TYPE_A;
+                       cmd_form = FORM_N;
+               }
+       | A SP form_code
+               {
+                       cmd_type = TYPE_A;
+                       cmd_form = $3;
+               }
+       | E
+               {
+                       cmd_type = TYPE_E;
+                       cmd_form = FORM_N;
+               }
+       | E SP form_code
+               {
+                       cmd_type = TYPE_E;
+                       cmd_form = $3;
+               }
+       | I
+               {
+                       cmd_type = TYPE_I;
+               }
+       | L
+               {
+                       cmd_type = TYPE_L;
+                       cmd_bytesz = NBBY;
+               }
+       | L SP byte_size
+               {
+                       cmd_type = TYPE_L;
+                       cmd_bytesz = $3;
+               }
+               /* this is for a bug in the BBN ftp */
+       | L byte_size
+               {
+                       cmd_type = TYPE_L;
+                       cmd_bytesz = $2;
+               }
+       ;
+
+struct_code
+       : F
+               {
+                       $$ = STRU_F;
+               }
+       | R
+               {
+                       $$ = STRU_R;
+               }
+       | P
+               {
+                       $$ = STRU_P;
+               }
+       ;
+
+mode_code
+       : S
+               {
+                       $$ = MODE_S;
+               }
+       | B
+               {
+                       $$ = MODE_B;
+               }
+       | C
+               {
+                       $$ = MODE_C;
+               }
+       ;
+
+pathname
+       : pathstring
+               {
+                       /*
+                        * Problem: this production is used for all pathname
+                        * processing, but only gives a 550 error reply.
+                        * This is a valid reply in some cases but not in others.
+                        */
+                       if (logged_in && $1 && *$1 == '~') {
+                               glob_t gl;
+                               int flags =
+                                GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+                               memset(&gl, 0, sizeof(gl));
+                               if (glob($1, flags, NULL, &gl) ||
+                                   gl.gl_pathc == 0) {
+                                       reply(550, "not found");
+                                       $$ = NULL;
+                               } else {
+                                       $$ = strdup(gl.gl_pathv[0]);
+                               }
+                               globfree(&gl);
+                               free($1);
+                       } else
+                               $$ = $1;
+               }
+       ;
+
+pathstring
+       : STRING
+       ;
+
+octal_number
+       : NUMBER
+               {
+                       int ret, dec, multby, digit;
+
+                       /*
+                        * Convert a number that was read as decimal number
+                        * to what it would be if it had been read as octal.
+                        */
+                       dec = $1;
+                       multby = 1;
+                       ret = 0;
+                       while (dec) {
+                               digit = dec%10;
+                               if (digit > 7) {
+                                       ret = -1;
+                                       break;
+                               }
+                               ret += digit * multby;
+                               multby *= 8;
+                               dec /= 10;
+                       }
+                       $$ = ret;
+               }
+       ;
+
+
+check_login
+       : /* empty */
+               {
+                       if (logged_in)
+                               $$ = 1;
+                       else {
+                               reply(530, "Please login with USER and PASS.");
+                               $$ = 0;
+                       }
+               }
+       ;
+
+%%
+
+extern jmp_buf errcatch;
+
+#define        CMD     0       /* beginning of command */
+#define        ARGS    1       /* expect miscellaneous arguments */
+#define        STR1    2       /* expect SP followed by STRING */
+#define        STR2    3       /* expect STRING */
+#define        OSTR    4       /* optional SP then STRING */
+#define        ZSTR1   5       /* SP then optional STRING */
+#define        ZSTR2   6       /* optional STRING after SP */
+#define        SITECMD 7       /* SITE command */
+#define        NSTR    8       /* Number followed by a string */
+
+struct tab {
+       char    *name;
+       short   token;
+       short   state;
+       short   implemented;    /* 1 if command is implemented */
+       char    *help;
+};
+
+struct tab cmdtab[] = {                /* In order defined in RFC 765 */
+       { "USER", USER, STR1, 1,        "<sp> username" },
+       { "PASS", PASS, ZSTR1, 1,       "<sp> password" },
+       { "ACCT", ACCT, STR1, 0,        "(specify account)" },
+       { "SMNT", SMNT, ARGS, 0,        "(structure mount)" },
+       { "REIN", REIN, ARGS, 0,        "(reinitialize server state)" },
+       { "QUIT", QUIT, ARGS, 1,        "(terminate service)", },
+       { "PORT", PORT, ARGS, 1,        "<sp> b0, b1, b2, b3, b4" },
+       { "PASV", PASV, ARGS, 1,        "(set server in passive mode)" },
+       { "TYPE", TYPE, ARGS, 1,        "<sp> [ A | E | I | L ]" },
+       { "STRU", STRU, ARGS, 1,        "(specify file structure)" },
+       { "MODE", MODE, ARGS, 1,        "(specify transfer mode)" },
+       { "RETR", RETR, STR1, 1,        "<sp> file-name" },
+       { "STOR", STOR, STR1, 1,        "<sp> file-name" },
+       { "APPE", APPE, STR1, 1,        "<sp> file-name" },
+       { "MLFL", MLFL, OSTR, 0,        "(mail file)" },
+       { "MAIL", MAIL, OSTR, 0,        "(mail to user)" },
+       { "MSND", MSND, OSTR, 0,        "(mail send to terminal)" },
+       { "MSOM", MSOM, OSTR, 0,        "(mail send to terminal or mailbox)" },
+       { "MSAM", MSAM, OSTR, 0,        "(mail send to terminal and mailbox)" },
+       { "MRSQ", MRSQ, OSTR, 0,        "(mail recipient scheme question)" },
+       { "MRCP", MRCP, STR1, 0,        "(mail recipient)" },
+       { "ALLO", ALLO, ARGS, 1,        "allocate storage (vacuously)" },
+       { "REST", REST, ARGS, 1,        "<sp> offset (restart command)" },
+       { "RNFR", RNFR, STR1, 1,        "<sp> file-name" },
+       { "RNTO", RNTO, STR1, 1,        "<sp> file-name" },
+       { "ABOR", ABOR, ARGS, 1,        "(abort operation)" },
+       { "DELE", DELE, STR1, 1,        "<sp> file-name" },
+       { "CWD",  CWD,  OSTR, 1,        "[ <sp> directory-name ]" },
+       { "XCWD", CWD,  OSTR, 1,        "[ <sp> directory-name ]" },
+       { "LIST", LIST, OSTR, 1,        "[ <sp> path-name ]" },
+       { "NLST", NLST, OSTR, 1,        "[ <sp> path-name ]" },
+       { "SITE", SITE, SITECMD, 1,     "site-cmd [ <sp> arguments ]" },
+       { "SYST", SYST, ARGS, 1,        "(get type of operating system)" },
+       { "STAT", STAT, OSTR, 1,        "[ <sp> path-name ]" },
+       { "HELP", HELP, OSTR, 1,        "[ <sp> <string> ]" },
+       { "NOOP", NOOP, ARGS, 1,        "" },
+       { "MKD",  MKD,  STR1, 1,        "<sp> path-name" },
+       { "XMKD", MKD,  STR1, 1,        "<sp> path-name" },
+       { "RMD",  RMD,  STR1, 1,        "<sp> path-name" },
+       { "XRMD", RMD,  STR1, 1,        "<sp> path-name" },
+       { "PWD",  PWD,  ARGS, 1,        "(return current directory)" },
+       { "XPWD", PWD,  ARGS, 1,        "(return current directory)" },
+       { "CDUP", CDUP, ARGS, 1,        "(change to parent directory)" },
+       { "XCUP", CDUP, ARGS, 1,        "(change to parent directory)" },
+       { "STOU", STOU, STR1, 1,        "<sp> file-name" },
+       { "SIZE", SIZE, OSTR, 1,        "<sp> path-name" },
+       { "MDTM", MDTM, OSTR, 1,        "<sp> path-name" },
+       { NULL,   0,    0,    0,        0 }
+};
+
+struct tab sitetab[] = {
+       { "UMASK", UMASK, ARGS, 1,      "[ <sp> umask ]" },
+       { "IDLE", IDLE, ARGS, 1,        "[ <sp> maximum-idle-time ]" },
+       { "CHMOD", CHMOD, NSTR, 1,      "<sp> mode <sp> file-name" },
+       { "HELP", HELP, OSTR, 1,        "[ <sp> <string> ]" },
+       { NULL,   0,    0,    0,        0 }
+};
+
+static char    *copy __P((char *));
+static void     help __P((struct tab *, char *));
+static struct tab *
+                lookup __P((struct tab *, char *));
+static void     sizecmd __P((char *));
+static void     toolong __P((int));
+static int      yylex __P((void));
+
+static struct tab *
+lookup(p, cmd)
+       struct tab *p;
+       char *cmd;
+{
+
+       for (; p->name != NULL; p++)
+               if (strcmp(cmd, p->name) == 0)
+                       return (p);
+       return (0);
+}
+
+#include <arpa/telnet.h>
+
+/*
+ * getline - a hacked up version of fgets to ignore TELNET escape codes.
+ */
+char *
+getline(s, n, iop)
+       char *s;
+       int n;
+       FILE *iop;
+{
+       int c;
+       register char *cs;
+
+       cs = s;
+/* tmpline may contain saved command from urgent mode interruption */
+       for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
+               *cs++ = tmpline[c];
+               if (tmpline[c] == '\n') {
+                       *cs++ = '\0';
+                       if (debug)
+                               syslog(LOG_DEBUG, "command: %s", s);
+                       tmpline[0] = '\0';
+                       return(s);
+               }
+               if (c == 0)
+                       tmpline[0] = '\0';
+       }
+       while ((c = getc(iop)) != EOF) {
+               c &= 0377;
+               if (c == IAC) {
+                   if ((c = getc(iop)) != EOF) {
+                       c &= 0377;
+                       switch (c) {
+                       case WILL:
+                       case WONT:
+                               c = getc(iop);
+                               printf("%c%c%c", IAC, DONT, 0377&c);
+                               (void) fflush(stdout);
+                               continue;
+                       case DO:
+                       case DONT:
+                               c = getc(iop);
+                               printf("%c%c%c", IAC, WONT, 0377&c);
+                               (void) fflush(stdout);
+                               continue;
+                       case IAC:
+                               break;
+                       default:
+                               continue;       /* ignore command */
+                       }
+                   }
+               }
+               *cs++ = c;
+               if (--n <= 0 || c == '\n')
+                       break;
+       }
+       if (c == EOF && cs == s)
+               return (NULL);
+       *cs++ = '\0';
+       if (debug) {
+               if (!guest && strncasecmp("pass ", s, 5) == 0) {
+                       /* Don't syslog passwords */
+                       syslog(LOG_DEBUG, "command: %.5s ???", s);
+               } else {
+                       register char *cp;
+                       register int len;
+
+                       /* Don't syslog trailing CR-LF */
+                       len = strlen(s);
+                       cp = s + len - 1;
+                       while (cp >= s && (*cp == '\n' || *cp == '\r')) {
+                               --cp;
+                               --len;
+                       }
+                       syslog(LOG_DEBUG, "command: %.*s", len, s);
+               }
+       }
+       return (s);
+}
+
+static void
+toolong(signo)
+       int signo;
+{
+
+       reply(421,
+           "Timeout (%d seconds): closing control connection.", timeout);
+       if (logging)
+               syslog(LOG_INFO, "User %s timed out after %d seconds",
+                   (pw ? pw -> pw_name : "unknown"), timeout);
+       dologout(1);
+}
+
+static int
+yylex()
+{
+       static int cpos, state;
+       char *cp, *cp2;
+       struct tab *p;
+       int n;
+       char c;
+
+       for (;;) {
+               switch (state) {
+
+               case CMD:
+                       (void) signal(SIGALRM, toolong);
+                       (void) alarm((unsigned) timeout);
+                       if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
+                               reply(221, "You could at least say goodbye.");
+                               dologout(0);
+                       }
+                       (void) alarm(0);
+#ifdef SETPROCTITLE
+                       if (strncasecmp(cbuf, "PASS", 4) != NULL)
+                               setproctitle("%s: %s", proctitle, cbuf);
+#endif /* SETPROCTITLE */
+                       if ((cp = strchr(cbuf, '\r'))) {
+                               *cp++ = '\n';
+                               *cp = '\0';
+                       }
+                       if ((cp = strpbrk(cbuf, " \n")))
+                               cpos = cp - cbuf;
+                       if (cpos == 0)
+                               cpos = 4;
+                       c = cbuf[cpos];
+                       cbuf[cpos] = '\0';
+                       upper(cbuf);
+                       p = lookup(cmdtab, cbuf);
+                       cbuf[cpos] = c;
+                       if (p != 0) {
+                               if (p->implemented == 0) {
+                                       nack(p->name);
+                                       longjmp(errcatch,0);
+                                       /* NOTREACHED */
+                               }
+                               state = p->state;
+                               yylval.s = p->name;
+                               return (p->token);
+                       }
+                       break;
+
+               case SITECMD:
+                       if (cbuf[cpos] == ' ') {
+                               cpos++;
+                               return (SP);
+                       }
+                       cp = &cbuf[cpos];
+                       if ((cp2 = strpbrk(cp, " \n")))
+                               cpos = cp2 - cbuf;
+                       c = cbuf[cpos];
+                       cbuf[cpos] = '\0';
+                       upper(cp);
+                       p = lookup(sitetab, cp);
+                       cbuf[cpos] = c;
+                       if (p != 0) {
+                               if (p->implemented == 0) {
+                                       state = CMD;
+                                       nack(p->name);
+                                       longjmp(errcatch,0);
+                                       /* NOTREACHED */
+                               }
+                               state = p->state;
+                               yylval.s = p->name;
+                               return (p->token);
+                       }
+                       state = CMD;
+                       break;
+
+               case OSTR:
+                       if (cbuf[cpos] == '\n') {
+                               state = CMD;
+                               return (CRLF);
+                       }
+                       /* FALLTHROUGH */
+
+               case STR1:
+               case ZSTR1:
+               dostr1:
+                       if (cbuf[cpos] == ' ') {
+                               cpos++;
+                               state = state == OSTR ? STR2 : ++state;
+                               return (SP);
+                       }
+                       break;
+
+               case ZSTR2:
+                       if (cbuf[cpos] == '\n') {
+                               state = CMD;
+                               return (CRLF);
+                       }
+                       /* FALLTHROUGH */
+
+               case STR2:
+                       cp = &cbuf[cpos];
+                       n = strlen(cp);
+                       cpos += n - 1;
+                       /*
+                        * Make sure the string is nonempty and \n terminated.
+                        */
+                       if (n > 1 && cbuf[cpos] == '\n') {
+                               cbuf[cpos] = '\0';
+                               yylval.s = copy(cp);
+                               cbuf[cpos] = '\n';
+                               state = ARGS;
+                               return (STRING);
+                       }
+                       break;
+
+               case NSTR:
+                       if (cbuf[cpos] == ' ') {
+                               cpos++;
+                               return (SP);
+                       }
+                       if (isdigit(cbuf[cpos])) {
+                               cp = &cbuf[cpos];
+                               while (isdigit(cbuf[++cpos]))
+                                       ;
+                               c = cbuf[cpos];
+                               cbuf[cpos] = '\0';
+                               yylval.i = atoi(cp);
+                               cbuf[cpos] = c;
+                               state = STR1;
+                               return (NUMBER);
+                       }
+                       state = STR1;
+                       goto dostr1;
+
+               case ARGS:
+                       if (isdigit(cbuf[cpos])) {
+                               cp = &cbuf[cpos];
+                               while (isdigit(cbuf[++cpos]))
+                                       ;
+                               c = cbuf[cpos];
+                               cbuf[cpos] = '\0';
+                               yylval.i = atoi(cp);
+                               cbuf[cpos] = c;
+                               return (NUMBER);
+                       }
+                       switch (cbuf[cpos++]) {
+
+                       case '\n':
+                               state = CMD;
+                               return (CRLF);
+
+                       case ' ':
+                               return (SP);
+
+                       case ',':
+                               return (COMMA);
+
+                       case 'A':
+                       case 'a':
+                               return (A);
+
+                       case 'B':
+                       case 'b':
+                               return (B);
+
+                       case 'C':
+                       case 'c':
+                               return (C);
+
+                       case 'E':
+                       case 'e':
+                               return (E);
+
+                       case 'F':
+                       case 'f':
+                               return (F);
+
+                       case 'I':
+                       case 'i':
+                               return (I);
+
+                       case 'L':
+                       case 'l':
+                               return (L);
+
+                       case 'N':
+                       case 'n':
+                               return (N);
+
+                       case 'P':
+                       case 'p':
+                               return (P);
+
+                       case 'R':
+                       case 'r':
+                               return (R);
+
+                       case 'S':
+                       case 's':
+                               return (S);
+
+                       case 'T':
+                       case 't':
+                               return (T);
+
+                       }
+                       break;
+
+               default:
+                       fatal("Unknown state in scanner.");
+               }
+               yyerror((char *) 0);
+               state = CMD;
+               longjmp(errcatch,0);
+       }
+}
+
+void
+upper(s)
+       char *s;
+{
+       while (*s != '\0') {
+               if (islower(*s))
+                       *s = toupper(*s);
+               s++;
+       }
+}
+
+static char *
+copy(s)
+       char *s;
+{
+       char *p;
+
+       p = malloc((unsigned) strlen(s) + 1);
+       if (p == NULL)
+               fatal("Ran out of memory.");
+       (void) strcpy(p, s);
+       return (p);
+}
+
+static void
+help(ctab, s)
+       struct tab *ctab;
+       char *s;
+{
+       struct tab *c;
+       int width, NCMDS;
+       char *type;
+
+       if (ctab == sitetab)
+               type = "SITE ";
+       else
+               type = "";
+       width = 0, NCMDS = 0;
+       for (c = ctab; c->name != NULL; c++) {
+               int len = strlen(c->name);
+
+               if (len > width)
+                       width = len;
+               NCMDS++;
+       }
+       width = (width + 8) &~ 7;
+       if (s == 0) {
+               int i, j, w;
+               int columns, lines;
+
+               lreply(214, "The following %scommands are recognized %s.",
+                   type, "(* =>'s unimplemented)");
+               columns = 76 / width;
+               if (columns == 0)
+                       columns = 1;
+               lines = (NCMDS + columns - 1) / columns;
+               for (i = 0; i < lines; i++) {
+                       printf("   ");
+                       for (j = 0; j < columns; j++) {
+                               c = ctab + j * lines + i;
+                               printf("%s%c", c->name,
+                                       c->implemented ? ' ' : '*');
+                               if (c + lines >= &ctab[NCMDS])
+                                       break;
+                               w = strlen(c->name) + 1;
+                               while (w < width) {
+                                       putchar(' ');
+                                       w++;
+                               }
+                       }
+                       printf("\r\n");
+               }
+               (void) fflush(stdout);
+               reply(214, "Direct comments to ftp-bugs@%s.", hostname);
+               return;
+       }
+       upper(s);
+       c = lookup(ctab, s);
+       if (c == (struct tab *)0) {
+               reply(502, "Unknown command %s.", s);
+               return;
+       }
+       if (c->implemented)
+               reply(214, "Syntax: %s%s %s", type, c->name, c->help);
+       else
+               reply(214, "%s%-*s\t%s; unimplemented.", type, width,
+                   c->name, c->help);
+}
+
+static void
+sizecmd(filename)
+       char *filename;
+{
+       switch (type) {
+       case TYPE_L:
+       case TYPE_I: {
+               struct stat stbuf;
+               if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode))
+                       reply(550, "%s: not a plain file.", filename);
+               else
+                       reply(213, "%qu", stbuf.st_size);
+               break; }
+       case TYPE_A: {
+               FILE *fin;
+               int c;
+               off_t count;
+               struct stat stbuf;
+               fin = fopen(filename, "r");
+               if (fin == NULL) {
+                       perror_reply(550, filename);
+                       return;
+               }
+               if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {
+                       reply(550, "%s: not a plain file.", filename);
+                       (void) fclose(fin);
+                       return;
+               }
+
+               count = 0;
+               while((c=getc(fin)) != EOF) {
+                       if (c == '\n')  /* will get expanded to \r\n */
+                               count++;
+                       count++;
+               }
+               (void) fclose(fin);
+
+               reply(213, "%qd", count);
+               break; }
+       default:
+               reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
+       }
+}
diff --git a/ftpd.tproj/ftpd.8 b/ftpd.tproj/ftpd.8
new file mode 100644 (file)
index 0000000..eb93c38
--- /dev/null
@@ -0,0 +1,291 @@
+.\" Copyright (c) 1985, 1988, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)ftpd.8     8.3 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt FTPD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm ftpd
+.Nd
+Internet File Transfer Protocol server
+.Sh SYNOPSIS
+.Nm ftpd
+.Op Fl dl
+.Op Fl T Ar maxtimeout
+.Op Fl t Ar timeout
+.Sh DESCRIPTION
+.Nm Ftpd
+is the
+Internet File Transfer Protocol
+server process.  The server uses the
+.Tn TCP
+protocol
+and listens at the port specified in the
+.Dq ftp
+service specification; see
+.Xr services 5 .
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl d
+Debugging information is written to the syslog using LOG_FTP.
+.It Fl l
+Each successful and failed 
+.Xr ftp 1
+session is logged using syslog with a facility of LOG_FTP.
+If this option is specified twice, the retrieve (get), store (put), append,
+delete, make directory, remove directory and rename operations and
+their filename arguments are also logged.
+.It Fl T
+A client may also request a different timeout period;
+the maximum period allowed may be set to
+.Ar timeout
+seconds with the
+.Fl T
+option.
+The default limit is 2 hours.
+.It Fl t
+The inactivity timeout period is set to
+.Ar timeout
+seconds (the default is 15 minutes).
+.El
+.Pp
+The file
+.Pa /etc/nologin
+can be used to disable ftp access.
+If the file exists,
+.Nm
+displays it and exits.
+If the file
+.Pa /etc/ftpwelcome
+exists,
+.Nm
+prints it before issuing the 
+.Dq ready
+message.
+If the file
+.Pa /etc/motd
+exists,
+.Nm
+prints it after a successful login.
+.Pp
+The ftp server currently supports the following ftp requests.
+The case of the requests is ignored.
+.Bl -column "Request" -offset indent
+.It Request Ta "Description"
+.It ABOR Ta "abort previous command"
+.It ACCT Ta "specify account (ignored)"
+.It ALLO Ta "allocate storage (vacuously)"
+.It APPE Ta "append to a file"
+.It CDUP Ta "change to parent of current working directory"
+.It CWD Ta "change working directory"
+.It DELE Ta "delete a file"
+.It HELP Ta "give help information"
+.It LIST Ta "give list files in a directory" Pq Dq Li "ls -lgA"
+.It MKD Ta "make a directory"
+.It MDTM Ta "show last modification time of file"
+.It MODE Ta "specify data transfer" Em mode
+.It NLST Ta "give name list of files in directory"
+.It NOOP Ta "do nothing"
+.It PASS Ta "specify password"
+.It PASV Ta "prepare for server-to-server transfer"
+.It PORT Ta "specify data connection port"
+.It PWD Ta "print the current working directory"
+.It QUIT Ta "terminate session"
+.It REST Ta "restart incomplete transfer"
+.It RETR Ta "retrieve a file"
+.It RMD Ta "remove a directory"
+.It RNFR Ta "specify rename-from file name"
+.It RNTO Ta "specify rename-to file name"
+.It SITE Ta "non-standard commands (see next section)"
+.It SIZE Ta "return size of file"
+.It STAT Ta "return status of server"
+.It STOR Ta "store a file"
+.It STOU Ta "store a file with a unique name"
+.It STRU Ta "specify data transfer" Em structure
+.It SYST Ta "show operating system type of server system"
+.It TYPE Ta "specify data transfer" Em type
+.It USER Ta "specify user name"
+.It XCUP Ta "change to parent of current working directory (deprecated)"
+.It XCWD Ta "change working directory (deprecated)"
+.It XMKD Ta "make a directory (deprecated)"
+.It XPWD Ta "print the current working directory (deprecated)"
+.It XRMD Ta "remove a directory (deprecated)"
+.El
+.Pp
+The following non-standard or
+.Tn UNIX
+specific commands are supported
+by the
+SITE request.
+.Pp
+.Bl -column Request -offset indent
+.It Sy Request Ta Sy Description
+.It UMASK Ta change umask, e.g. ``SITE UMASK 002''
+.It IDLE Ta set idle-timer, e.g. ``SITE IDLE 60''
+.It CHMOD Ta change mode of a file, e.g. ``SITE CHMOD 755 filename''
+.It HELP Ta give help information.
+.El
+.Pp
+The remaining ftp requests specified in Internet RFC 959
+are
+recognized, but not implemented.
+MDTM and SIZE are not specified in RFC 959, but will appear in the
+next updated FTP RFC.
+.Pp
+The ftp server will abort an active file transfer only when the
+ABOR
+command is preceded by a Telnet "Interrupt Process" (IP)
+signal and a Telnet "Synch" signal in the command Telnet stream,
+as described in Internet RFC 959.
+If a
+STAT
+command is received during a data transfer, preceded by a Telnet IP
+and Synch, transfer status will be returned.
+.Pp
+.Nm Ftpd
+interprets file names according to the
+.Dq globbing
+conventions used by
+.Xr csh 1 .
+This allows users to utilize the metacharacters
+.Dq Li \&*?[]{}~ .
+.Pp
+.Nm Ftpd
+authenticates users according to three rules. 
+.Pp
+.Bl -enum -offset indent
+.It
+The login name must be in the password data base,
+.Pa /etc/passwd ,
+and not have a null password.
+In this case a password must be provided by the client before any
+file operations may be performed.
+.It
+The login name must not appear in the file
+.Pa /etc/ftpusers .
+.It
+The user must have a standard shell returned by 
+.Xr getusershell 3 .
+.It
+If the user name is
+.Dq anonymous
+or
+.Dq ftp ,
+an
+anonymous ftp account must be present in the password
+file (user
+.Dq ftp ) .
+In this case the user is allowed
+to log in by specifying any password (by convention an email address for
+the user should be used as the password).
+.El
+.Pp
+In the last case, 
+.Nm ftpd
+takes special measures to restrict the client's access privileges.
+The server performs a 
+.Xr chroot 2
+to the home directory of the
+.Dq ftp
+user.
+In order that system security is not breached, it is recommended
+that the
+.Dq ftp
+subtree be constructed with care, following these rules:
+.Bl -tag -width "~ftp/pub" -offset indent
+.It Pa ~ftp
+Make the home directory owned by
+.Dq root
+and unwritable by anyone.
+.ne 1i
+.It Pa ~ftp/bin
+Make this directory owned by
+.Dq root
+and unwritable by anyone (mode 555).
+The program
+.Xr ls 1
+must be present to support the list command.
+This program should be mode 111.
+.It Pa ~ftp/etc
+Make this directory owned by
+.Dq root
+and unwritable by anyone (mode 555).
+The files
+.Xr passwd 5
+and
+.Xr group 5
+must be present for the 
+.Xr ls
+command to be able to produce owner names rather than numbers.
+The password field in
+.Xr passwd
+is not used, and should not contain real passwords.
+The file
+.Pa motd ,
+if present, will be printed after a successful login.
+These files should be mode 444.
+.It Pa ~ftp/pub
+Make this directory mode 777 and owned by
+.Dq ftp .
+Guests
+can then place files which are to be accessible via the anonymous
+account in this directory.
+.El
+.Sh FILES
+.Bl -tag -width /etc/ftpwelcome -compact
+.It Pa /etc/ftpusers
+List of unwelcome/restricted users.
+.It Pa /etc/ftpwelcome
+Welcome notice.
+.It Pa /etc/motd
+Welcome notice after login.
+.It Pa /etc/nologin
+Displayed and access refused.
+.El
+.Sh SEE ALSO
+.Xr ftp 1 ,
+.Xr getusershell 3 ,
+.Xr syslogd 8
+.Sh BUGS
+The server must run as the super-user
+to create sockets with privileged port numbers.  It maintains
+an effective user id of the logged in user, reverting to
+the super-user only when binding addresses to sockets.  The
+possible security holes have been extensively
+scrutinized, but are possibly incomplete.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/ftpd.tproj/ftpd.c b/ftpd.tproj/ftpd.c
new file mode 100644 (file)
index 0000000..4071f02
--- /dev/null
@@ -0,0 +1,1686 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ftpd.c     8.5 (Berkeley) 4/28/95";
+#endif /* not lint */
+
+/* XXX this is to get around a compiler bug with long long's on ppc */
+#pragma CC_OPT_OFF
+
+/*
+ * FTP server.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#define        FTP_NAMES
+#include <arpa/ftp.h>
+#include <arpa/inet.h>
+#include <arpa/telnet.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+#include "extern.h"
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+static char version[] = "Version 6.00";
+
+extern off_t restart_point;
+extern char cbuf[];
+
+struct sockaddr_in ctrl_addr;
+struct sockaddr_in data_source;
+struct sockaddr_in data_dest;
+struct sockaddr_in his_addr;
+struct sockaddr_in pasv_addr;
+
+int    data;
+jmp_buf        errcatch, urgcatch;
+int    logged_in;
+struct passwd *pw;
+int    debug;
+int    timeout = 900;    /* timeout after 15 minutes of inactivity */
+int    maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
+int    logging;
+int    guest;
+int    type;
+int    form;
+int    stru;                   /* avoid C keyword */
+int    mode;
+int    usedefault = 1;         /* for data transfers */
+int    pdata = -1;             /* for passive mode */
+sig_atomic_t transflag;
+off_t  file_size;
+off_t  byte_count;
+#if !defined(CMASK) || CMASK == 0
+#undef CMASK
+#define CMASK 027
+#endif
+int    defumask = CMASK;               /* default umask value */
+char   tmpline[7];
+char   hostname[MAXHOSTNAMELEN];
+char   remotehost[MAXHOSTNAMELEN];
+
+/*
+ * Timeout intervals for retrying connections
+ * to hosts that don't accept PORT cmds.  This
+ * is a kludge, but given the problems with TCP...
+ */
+#define        SWAITMAX        90      /* wait at most 90 seconds */
+#define        SWAITINT        5       /* interval between retries */
+
+int    swaitmax = SWAITMAX;
+int    swaitint = SWAITINT;
+
+#ifdef SETPROCTITLE
+char   **Argv = NULL;          /* pointer to argument vector */
+char   *LastArgv = NULL;       /* end of argv */
+char   proctitle[LINE_MAX];    /* initial part of title */
+#endif /* SETPROCTITLE */
+
+#define LOGCMD(cmd, file) \
+       if (logging > 1) \
+           syslog(LOG_INFO,"%s %s%s", cmd, \
+               *(file) == '/' ? "" : curdir(), file);
+#define LOGCMD2(cmd, file1, file2) \
+        if (logging > 1) \
+           syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
+               *(file1) == '/' ? "" : curdir(), file1, \
+               *(file2) == '/' ? "" : curdir(), file2);
+#define LOGBYTES(cmd, file, cnt) \
+       if (logging > 1) { \
+               if (cnt == (off_t)-1) \
+                   syslog(LOG_INFO,"%s %s%s", cmd, \
+                       *(file) == '/' ? "" : curdir(), file); \
+               else \
+                   syslog(LOG_INFO, "%s %s%s = %qd bytes", \
+                       cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
+       }
+
+static void     ack __P((char *));
+static void     myoob __P((int));
+static int      checkuser __P((char *));
+static FILE    *dataconn __P((char *, off_t, char *));
+static void     dolog __P((struct sockaddr_in *));
+static char    *curdir __P((void));
+static void     end_login __P((void));
+static FILE    *getdatasock __P((char *));
+static char    *gunique __P((char *));
+static void     lostconn __P((int));
+static int      receive_data __P((FILE *, FILE *));
+static void     send_data __P((FILE *, FILE *, off_t));
+static struct passwd *
+                sgetpwnam __P((char *));
+static char    *sgetsave __P((char *));
+
+static char *
+curdir()
+{
+       static char path[MAXPATHLEN+1+1];       /* path + '/' + '\0' */
+
+       if (getcwd(path, sizeof(path)-2) == NULL)
+               return ("");
+       if (path[1] != '\0')            /* special case for root dir. */
+               strcat(path, "/");
+       /* For guest account, skip / since it's chrooted */
+       return (guest ? path+1 : path);
+}
+
+int
+main(argc, argv, envp)
+       int argc;
+       char *argv[];
+       char **envp;
+{
+       int addrlen, ch, on = 1, tos;
+       char *cp, line[LINE_MAX];
+       FILE *fd;
+
+       /*
+        * LOG_NDELAY sets up the logging connection immediately,
+        * necessary for anonymous ftp's that chroot and can't do it later.
+        */
+       openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
+       addrlen = sizeof(his_addr);
+       if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
+               syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
+               exit(1);
+       }
+       addrlen = sizeof(ctrl_addr);
+       if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
+               syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
+               exit(1);
+       }
+#ifdef IP_TOS
+       tos = IPTOS_LOWDELAY;
+       if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+               syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+       data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
+       debug = 0;
+#ifdef SETPROCTITLE
+       /*
+        *  Save start and extent of argv for setproctitle.
+        */
+       Argv = argv;
+       while (*envp)
+               envp++;
+       LastArgv = envp[-1] + strlen(envp[-1]);
+#endif /* SETPROCTITLE */
+
+       while ((ch = getopt(argc, argv, "dlt:T:u:v")) != -1) {
+               switch (ch) {
+               case 'd':
+                       debug = 1;
+                       break;
+
+               case 'l':
+                       logging++;      /* > 1 == extra logging */
+                       break;
+
+               case 't':
+                       timeout = atoi(optarg);
+                       if (maxtimeout < timeout)
+                               maxtimeout = timeout;
+                       break;
+
+               case 'T':
+                       maxtimeout = atoi(optarg);
+                       if (timeout > maxtimeout)
+                               timeout = maxtimeout;
+                       break;
+
+               case 'u':
+                   {
+                       long val = 0;
+
+                       val = strtol(optarg, &optarg, 8);
+                       if (*optarg != '\0' || val < 0)
+                               warnx("bad value for -u");
+                       else
+                               defumask = val;
+                       break;
+                   }
+
+               case 'v':
+                       debug = 1;
+                       break;
+
+               default:
+                       warnx("unknown flag -%c ignored", optopt);
+                       break;
+               }
+       }
+       (void) freopen(_PATH_DEVNULL, "w", stderr);
+       (void) signal(SIGPIPE, lostconn);
+       (void) signal(SIGCHLD, SIG_IGN);
+       if ((int)signal(SIGURG, myoob) < 0)
+               syslog(LOG_ERR, "signal: %m");
+
+       /* Try to handle urgent data inline */
+#ifdef SO_OOBINLINE
+       if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)
+               syslog(LOG_ERR, "setsockopt: %m");
+#endif
+
+#ifdef F_SETOWN
+       if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
+               syslog(LOG_ERR, "fcntl F_SETOWN: %m");
+#endif
+       dolog(&his_addr);
+       /*
+        * Set up default state
+        */
+       data = -1;
+       type = TYPE_A;
+       form = FORM_N;
+       stru = STRU_F;
+       mode = MODE_S;
+       tmpline[0] = '\0';
+
+       /* If logins are disabled, print out the message. */
+       if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
+               while (fgets(line, sizeof(line), fd) != NULL) {
+                       if ((cp = strchr(line, '\n')) != NULL)
+                               *cp = '\0';
+                       lreply(530, "%s", line);
+               }
+               (void) fflush(stdout);
+               (void) fclose(fd);
+               reply(530, "System not available.");
+               exit(0);
+       }
+       if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
+               while (fgets(line, sizeof(line), fd) != NULL) {
+                       if ((cp = strchr(line, '\n')) != NULL)
+                               *cp = '\0';
+                       lreply(220, "%s", line);
+               }
+               (void) fflush(stdout);
+               (void) fclose(fd);
+               /* reply(220,) must follow */
+       }
+       (void) gethostname(hostname, sizeof(hostname));
+       reply(220, "%s FTP server (%s) ready.", hostname, version);
+       (void) setjmp(errcatch);
+       for (;;)
+               (void) yyparse();
+       /* NOTREACHED */
+}
+
+static void
+lostconn(signo)
+       int signo;
+{
+
+       if (debug)
+               syslog(LOG_DEBUG, "lost connection");
+       dologout(-1);
+}
+
+static char ttyline[20];
+
+/*
+ * Helper function for sgetpwnam().
+ */
+static char *
+sgetsave(s)
+       char *s;
+{
+       char *new = malloc((unsigned) strlen(s) + 1);
+
+       if (new == NULL) {
+               perror_reply(421, "Local resource failure: malloc");
+               dologout(1);
+               /* NOTREACHED */
+       }
+       (void) strcpy(new, s);
+       return (new);
+}
+
+/*
+ * Save the result of a getpwnam.  Used for USER command, since
+ * the data returned must not be clobbered by any other command
+ * (e.g., globbing).
+ */
+static struct passwd *
+sgetpwnam(name)
+       char *name;
+{
+       static struct passwd save;
+       struct passwd *p;
+
+       if ((p = getpwnam(name)) == NULL)
+               return (p);
+       if (save.pw_name) {
+               free(save.pw_name);
+               free(save.pw_passwd);
+               free(save.pw_gecos);
+               free(save.pw_dir);
+               free(save.pw_shell);
+       }
+       save = *p;
+       save.pw_name = sgetsave(p->pw_name);
+       save.pw_passwd = sgetsave(p->pw_passwd);
+       save.pw_gecos = sgetsave(p->pw_gecos);
+       save.pw_dir = sgetsave(p->pw_dir);
+       save.pw_shell = sgetsave(p->pw_shell);
+       return (&save);
+}
+
+static int login_attempts;     /* number of failed login attempts */
+static int askpasswd;          /* had user command, ask for passwd */
+static char curname[10];       /* current USER name */
+
+/*
+ * USER command.
+ * Sets global passwd pointer pw if named account exists and is acceptable;
+ * sets askpasswd if a PASS command is expected.  If logged in previously,
+ * need to reset state.  If name is "ftp" or "anonymous", the name is not in
+ * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
+ * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
+ * requesting login privileges.  Disallow anyone who does not have a standard
+ * shell as returned by getusershell().  Disallow anyone mentioned in the file
+ * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
+ */
+void
+user(name)
+       char *name;
+{
+       char *cp, *shell;
+
+       if (logged_in) {
+               if (guest) {
+                       reply(530, "Can't change user from guest login.");
+                       return;
+               }
+               end_login();
+       }
+
+       guest = 0;
+       if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
+               if (checkuser("ftp") || checkuser("anonymous"))
+                       reply(530, "User %s access denied.", name);
+               else if ((pw = sgetpwnam("ftp")) != NULL) {
+                       guest = 1;
+                       askpasswd = 1;
+                       reply(331,
+                           "Guest login ok, type your name as password.");
+               } else
+                       reply(530, "User %s unknown.", name);
+               if (!askpasswd && logging)
+                       syslog(LOG_NOTICE,
+                           "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
+               return;
+       }
+       if (pw = sgetpwnam(name)) {
+               if ((shell = pw->pw_shell) == NULL || *shell == 0)
+                       shell = _PATH_BSHELL;
+               while ((cp = getusershell()) != NULL)
+                       if (strcmp(cp, shell) == 0)
+                               break;
+               endusershell();
+
+               if (cp == NULL || checkuser(name)) {
+                       reply(530, "User %s access denied.", name);
+                       if (logging)
+                               syslog(LOG_NOTICE,
+                                   "FTP LOGIN REFUSED FROM %s, %s",
+                                   remotehost, name);
+                       pw = (struct passwd *) NULL;
+                       return;
+               }
+       }
+       if (logging)
+               strncpy(curname, name, sizeof(curname)-1);
+       reply(331, "Password required for %s.", name);
+       askpasswd = 1;
+       /*
+        * Delay before reading passwd after first failed
+        * attempt to slow down passwd-guessing programs.
+        */
+       if (login_attempts)
+               sleep((unsigned) login_attempts);
+}
+
+/*
+ * Check if a user is in the file _PATH_FTPUSERS
+ */
+static int
+checkuser(name)
+       char *name;
+{
+       FILE *fd;
+       int found = 0;
+       char *p, line[BUFSIZ];
+
+       if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) {
+               while (fgets(line, sizeof(line), fd) != NULL)
+                       if ((p = strchr(line, '\n')) != NULL) {
+                               *p = '\0';
+                               if (line[0] == '#')
+                                       continue;
+                               if (strcmp(line, name) == 0) {
+                                       found = 1;
+                                       break;
+                               }
+                       }
+               (void) fclose(fd);
+       }
+       return (found);
+}
+
+/*
+ * Terminate login as previous user, if any, resetting state;
+ * used when USER command is given or login fails.
+ */
+static void
+end_login()
+{
+
+       (void) seteuid((uid_t)0);
+       if (logged_in)
+               logwtmp(ttyline, "", "");
+       pw = NULL;
+       logged_in = 0;
+       guest = 0;
+}
+
+void
+pass(passwd)
+       char *passwd;
+{
+       char *salt, *xpasswd;
+       FILE *fd;
+
+       if (logged_in || askpasswd == 0) {
+               reply(503, "Login with USER first.");
+               return;
+       }
+       askpasswd = 0;
+       if (!guest) {           /* "ftp" is only account allowed no password */
+               if (pw == NULL)
+                       salt = "xx";
+               else
+                       salt = pw->pw_passwd;
+               xpasswd = crypt(passwd, salt);
+               /* The strcmp does not catch null passwords! */
+               if (pw == NULL || *pw->pw_passwd == '\0' ||
+                   strcmp(xpasswd, pw->pw_passwd)) {
+                       reply(530, "Login incorrect.");
+                       if (logging)
+                               syslog(LOG_NOTICE,
+                                   "FTP LOGIN FAILED FROM %s, %s",
+                                   remotehost, curname);
+                       pw = NULL;
+                       if (login_attempts++ >= 5) {
+                               syslog(LOG_NOTICE,
+                                   "repeated login failures from %s",
+                                   remotehost);
+                               exit(0);
+                       }
+                       return;
+               }
+       }
+       login_attempts = 0;             /* this time successful */
+       if (setegid((gid_t)pw->pw_gid) < 0) {
+               reply(550, "Can't set gid.");
+               return;
+       }
+       (void) initgroups(pw->pw_name, pw->pw_gid);
+
+       /* open wtmp before chroot */
+       (void)sprintf(ttyline, "ftp%d", getpid());
+       logwtmp(ttyline, pw->pw_name, remotehost);
+       logged_in = 1;
+
+       if (guest) {
+               /*
+                * We MUST do a chdir() after the chroot. Otherwise
+                * the old current directory will be accessible as "."
+                * outside the new root!
+                */
+               if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
+                       reply(550, "Can't set guest privileges.");
+                       goto bad;
+               }
+       } else if (chdir(pw->pw_dir) < 0) {
+               if (chdir("/") < 0) {
+                       reply(530, "User %s: can't change directory to %s.",
+                           pw->pw_name, pw->pw_dir);
+                       goto bad;
+               } else
+                       lreply(230, "No directory! Logging in with home=/");
+       }
+       if (seteuid((uid_t)pw->pw_uid) < 0) {
+               reply(550, "Can't set uid.");
+               goto bad;
+       }
+       /*
+        * Display a login message, if it exists.
+        * N.B. reply(230,) must follow the message.
+        */
+       if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
+               char *cp, line[LINE_MAX];
+
+               while (fgets(line, sizeof(line), fd) != NULL) {
+                       if ((cp = strchr(line, '\n')) != NULL)
+                               *cp = '\0';
+                       lreply(230, "%s", line);
+               }
+               (void) fflush(stdout);
+               (void) fclose(fd);
+       }
+       if (guest) {
+               reply(230, "Guest login ok, access restrictions apply.");
+#ifdef SETPROCTITLE
+               snprintf(proctitle, sizeof(proctitle),
+                   "%s: anonymous/%.*s", remotehost,
+                   sizeof(proctitle) - sizeof(remotehost) -
+                   sizeof(": anonymous/"), passwd);
+               setproctitle("%s", proctitle);
+#endif /* SETPROCTITLE */
+               if (logging)
+                       syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
+                           remotehost, passwd);
+       } else {
+               reply(230, "User %s logged in.", pw->pw_name);
+#ifdef SETPROCTITLE
+               snprintf(proctitle, sizeof(proctitle),
+                   "%s: %s", remotehost, pw->pw_name);
+               setproctitle("%s", proctitle);
+#endif /* SETPROCTITLE */
+               if (logging)
+                       syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
+                           remotehost, pw->pw_name);
+       }
+       (void) umask(defumask);
+       return;
+bad:
+       /* Forget all about it... */
+       end_login();
+}
+
+void
+retrieve(cmd, name)
+       char *cmd, *name;
+{
+       FILE *fin, *dout;
+       struct stat st;
+       int (*closefunc) __P((FILE *));
+
+       if (cmd == 0) {
+               fin = fopen(name, "r"), closefunc = fclose;
+               st.st_size = 0;
+       } else {
+               char line[BUFSIZ];
+
+               (void) sprintf(line, cmd, name), name = line;
+               fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
+               st.st_size = -1;
+               st.st_blksize = BUFSIZ;
+       }
+       if (fin == NULL) {
+               if (errno != 0) {
+                       perror_reply(550, name);
+                       if (cmd == 0) {
+                               LOGCMD("get", name);
+                       }
+               }
+               return;
+       }
+       byte_count = -1;
+       if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
+               reply(550, "%s: not a plain file.", name);
+               goto done;
+       }
+       if (restart_point) {
+               if (type == TYPE_A) {
+                       off_t i, n;
+                       int c;
+
+                       n = restart_point;
+                       i = 0;
+                       while (i++ < n) {
+                               if ((c=getc(fin)) == EOF) {
+                                       perror_reply(550, name);
+                                       goto done;
+                               }
+                               if (c == '\n')
+                                       i++;
+                       }
+               } else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
+                       perror_reply(550, name);
+                       goto done;
+               }
+       }
+       dout = dataconn(name, st.st_size, "w");
+       if (dout == NULL)
+               goto done;
+       send_data(fin, dout, st.st_blksize);
+       (void) fclose(dout);
+       data = -1;
+       pdata = -1;
+done:
+       if (cmd == 0)
+               LOGBYTES("get", name, byte_count);
+       (*closefunc)(fin);
+}
+
+void
+store(name, mode, unique)
+       char *name, *mode;
+       int unique;
+{
+       FILE *fout, *din;
+       struct stat st;
+       int (*closefunc) __P((FILE *));
+
+       if (unique && stat(name, &st) == 0 &&
+           (name = gunique(name)) == NULL) {
+               LOGCMD(*mode == 'w' ? "put" : "append", name);
+               return;
+       }
+
+       if (restart_point)
+               mode = "r+";
+       fout = fopen(name, mode);
+       closefunc = fclose;
+       if (fout == NULL) {
+               perror_reply(553, name);
+               LOGCMD(*mode == 'w' ? "put" : "append", name);
+               return;
+       }
+       byte_count = -1;
+       if (restart_point) {
+               if (type == TYPE_A) {
+                       off_t i, n;
+                       int c;
+
+                       n = restart_point;
+                       i = 0;
+                       while (i++ < n) {
+                               if ((c=getc(fout)) == EOF) {
+                                       perror_reply(550, name);
+                                       goto done;
+                               }
+                               if (c == '\n')
+                                       i++;
+                       }
+                       /*
+                        * We must do this seek to "current" position
+                        * because we are changing from reading to
+                        * writing.
+                        */
+                       if (fseek(fout, 0L, L_INCR) < 0) {
+                               perror_reply(550, name);
+                               goto done;
+                       }
+               } else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
+                       perror_reply(550, name);
+                       goto done;
+               }
+       }
+       din = dataconn(name, (off_t)-1, "r");
+       if (din == NULL)
+               goto done;
+       if (receive_data(din, fout) == 0) {
+               if (unique)
+                       reply(226, "Transfer complete (unique file name:%s).",
+                           name);
+               else
+                       reply(226, "Transfer complete.");
+       }
+       (void) fclose(din);
+       data = -1;
+       pdata = -1;
+done:
+       LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
+       (*closefunc)(fout);
+}
+
+static FILE *
+getdatasock(mode)
+       char *mode;
+{
+       int on = 1, s, t, tries;
+
+       if (data >= 0)
+               return (fdopen(data, mode));
+       (void) seteuid((uid_t)0);
+       s = socket(AF_INET, SOCK_STREAM, 0);
+       if (s < 0)
+               goto bad;
+       if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+           (char *) &on, sizeof(on)) < 0)
+               goto bad;
+       /* anchor socket to avoid multi-homing problems */
+       data_source.sin_family = AF_INET;
+       data_source.sin_addr = ctrl_addr.sin_addr;
+       for (tries = 1; ; tries++) {
+               if (bind(s, (struct sockaddr *)&data_source,
+                   sizeof(data_source)) >= 0)
+                       break;
+               if (errno != EADDRINUSE || tries > 10)
+                       goto bad;
+               sleep(tries);
+       }
+       (void) seteuid((uid_t)pw->pw_uid);
+#ifdef IP_TOS
+       on = IPTOS_THROUGHPUT;
+       if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
+               syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+       return (fdopen(s, mode));
+bad:
+       /* Return the real value of errno (close may change it) */
+       t = errno;
+       (void) seteuid((uid_t)pw->pw_uid);
+       (void) close(s);
+       errno = t;
+       return (NULL);
+}
+
+static FILE *
+dataconn(name, size, mode)
+       char *name;
+       off_t size;
+       char *mode;
+{
+       char sizebuf[32];
+       FILE *file;
+       int retry = 0, tos;
+
+       file_size = size;
+       byte_count = 0;
+       if (size != (off_t) -1)
+               (void) sprintf(sizebuf, " (%qd bytes)", size);
+       else
+               (void) strcpy(sizebuf, "");
+       if (pdata >= 0) {
+               struct sockaddr_in from;
+               int s, fromlen = sizeof(from);
+
+               s = accept(pdata, (struct sockaddr *)&from, &fromlen);
+               if (s < 0) {
+                       reply(425, "Can't open data connection.");
+                       (void) close(pdata);
+                       pdata = -1;
+                       return (NULL);
+               }
+               (void) close(pdata);
+               pdata = s;
+#ifdef IP_TOS
+               tos = IPTOS_LOWDELAY;
+               (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
+                   sizeof(int));
+#endif
+               reply(150, "Opening %s mode data connection for '%s'%s.",
+                    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+               return (fdopen(pdata, mode));
+       }
+       if (data >= 0) {
+               reply(125, "Using existing data connection for '%s'%s.",
+                   name, sizebuf);
+               usedefault = 1;
+               return (fdopen(data, mode));
+       }
+       if (usedefault)
+               data_dest = his_addr;
+       usedefault = 1;
+       file = getdatasock(mode);
+       if (file == NULL) {
+               reply(425, "Can't create data socket (%s,%d): %s.",
+                   inet_ntoa(data_source.sin_addr),
+                   ntohs(data_source.sin_port), strerror(errno));
+               return (NULL);
+       }
+       data = fileno(file);
+       while (connect(data, (struct sockaddr *)&data_dest,
+           sizeof(data_dest)) < 0) {
+               if (errno == EADDRINUSE && retry < swaitmax) {
+                       sleep((unsigned) swaitint);
+                       retry += swaitint;
+                       continue;
+               }
+               perror_reply(425, "Can't build data connection");
+               (void) fclose(file);
+               data = -1;
+               return (NULL);
+       }
+       reply(150, "Opening %s mode data connection for '%s'%s.",
+            type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+       return (file);
+}
+
+/*
+ * Tranfer the contents of "instr" to "outstr" peer using the appropriate
+ * encapsulation of the data subject * to Mode, Structure, and Type.
+ *
+ * NB: Form isn't handled.
+ */
+static void
+send_data(instr, outstr, blksize)
+       FILE *instr, *outstr;
+       off_t blksize;
+{
+       int c, cnt, filefd, netfd;
+       char *buf;
+
+       transflag++;
+       if (setjmp(urgcatch)) {
+               transflag = 0;
+               return;
+       }
+       switch (type) {
+
+       case TYPE_A:
+               while ((c = getc(instr)) != EOF) {
+                       byte_count++;
+                       if (c == '\n') {
+                               if (ferror(outstr))
+                                       goto data_err;
+                               (void) putc('\r', outstr);
+                       }
+                       (void) putc(c, outstr);
+               }
+               fflush(outstr);
+               transflag = 0;
+               if (ferror(instr))
+                       goto file_err;
+               if (ferror(outstr))
+                       goto data_err;
+               reply(226, "Transfer complete.");
+               return;
+
+       case TYPE_I:
+       case TYPE_L:
+               if ((buf = malloc((u_int)blksize)) == NULL) {
+                       transflag = 0;
+                       perror_reply(451, "Local resource failure: malloc");
+                       return;
+               }
+               netfd = fileno(outstr);
+               filefd = fileno(instr);
+               while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
+                   write(netfd, buf, cnt) == cnt)
+                       byte_count += cnt;
+               transflag = 0;
+               (void)free(buf);
+               if (cnt != 0) {
+                       if (cnt < 0)
+                               goto file_err;
+                       goto data_err;
+               }
+               reply(226, "Transfer complete.");
+               return;
+       default:
+               transflag = 0;
+               reply(550, "Unimplemented TYPE %d in send_data", type);
+               return;
+       }
+
+data_err:
+       transflag = 0;
+       perror_reply(426, "Data connection");
+       return;
+
+file_err:
+       transflag = 0;
+       perror_reply(551, "Error on input file");
+}
+
+/*
+ * Transfer data from peer to "outstr" using the appropriate encapulation of
+ * the data subject to Mode, Structure, and Type.
+ *
+ * N.B.: Form isn't handled.
+ */
+static int
+receive_data(instr, outstr)
+       FILE *instr, *outstr;
+{
+       int c;
+       int cnt, bare_lfs = 0;
+       char buf[BUFSIZ];
+
+       transflag++;
+       if (setjmp(urgcatch)) {
+               transflag = 0;
+               return (-1);
+       }
+       switch (type) {
+
+       case TYPE_I:
+       case TYPE_L:
+               while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
+                       if (write(fileno(outstr), buf, cnt) != cnt)
+                               goto file_err;
+                       byte_count += cnt;
+               }
+               if (cnt < 0)
+                       goto data_err;
+               transflag = 0;
+               return (0);
+
+       case TYPE_E:
+               reply(553, "TYPE E not implemented.");
+               transflag = 0;
+               return (-1);
+
+       case TYPE_A:
+               while ((c = getc(instr)) != EOF) {
+                       byte_count++;
+                       if (c == '\n')
+                               bare_lfs++;
+                       while (c == '\r') {
+                               if (ferror(outstr))
+                                       goto data_err;
+                               if ((c = getc(instr)) != '\n') {
+                                       (void) putc ('\r', outstr);
+                                       if (c == '\0' || c == EOF)
+                                               goto contin2;
+                               }
+                       }
+                       (void) putc(c, outstr);
+       contin2:        ;
+               }
+               fflush(outstr);
+               if (ferror(instr))
+                       goto data_err;
+               if (ferror(outstr))
+                       goto file_err;
+               transflag = 0;
+               if (bare_lfs) {
+                       lreply(226,
+               "WARNING! %d bare linefeeds received in ASCII mode",
+                           bare_lfs);
+               (void)printf("   File may not have transferred correctly.\r\n");
+               }
+               return (0);
+       default:
+               reply(550, "Unimplemented TYPE %d in receive_data", type);
+               transflag = 0;
+               return (-1);
+       }
+
+data_err:
+       transflag = 0;
+       perror_reply(426, "Data Connection");
+       return (-1);
+
+file_err:
+       transflag = 0;
+       perror_reply(452, "Error writing file");
+       return (-1);
+}
+
+void
+statfilecmd(filename)
+       char *filename;
+{
+       FILE *fin;
+       int c;
+       char line[LINE_MAX];
+
+       (void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
+       fin = ftpd_popen(line, "r");
+       lreply(211, "status of %s:", filename);
+       while ((c = getc(fin)) != EOF) {
+               if (c == '\n') {
+                       if (ferror(stdout)){
+                               perror_reply(421, "control connection");
+                               (void) ftpd_pclose(fin);
+                               dologout(1);
+                               /* NOTREACHED */
+                       }
+                       if (ferror(fin)) {
+                               perror_reply(551, filename);
+                               (void) ftpd_pclose(fin);
+                               return;
+                       }
+                       (void) putc('\r', stdout);
+               }
+               (void) putc(c, stdout);
+       }
+       (void) ftpd_pclose(fin);
+       reply(211, "End of Status");
+}
+
+void
+statcmd()
+{
+       struct sockaddr_in *sin;
+       u_char *a, *p;
+
+       lreply(211, "%s FTP server status:", hostname, version);
+       printf("     %s\r\n", version);
+       printf("     Connected to %s", remotehost);
+       if (!isdigit(remotehost[0]))
+               printf(" (%s)", inet_ntoa(his_addr.sin_addr));
+       printf("\r\n");
+       if (logged_in) {
+               if (guest)
+                       printf("     Logged in anonymously\r\n");
+               else
+                       printf("     Logged in as %s\r\n", pw->pw_name);
+       } else if (askpasswd)
+               printf("     Waiting for password\r\n");
+       else
+               printf("     Waiting for user name\r\n");
+       printf("     TYPE: %s", typenames[type]);
+       if (type == TYPE_A || type == TYPE_E)
+               printf(", FORM: %s", formnames[form]);
+       if (type == TYPE_L)
+#if NBBY == 8
+               printf(" %d", NBBY);
+#else
+               printf(" %d", bytesize);        /* need definition! */
+#endif
+       printf("; STRUcture: %s; transfer MODE: %s\r\n",
+           strunames[stru], modenames[mode]);
+       if (data != -1)
+               printf("     Data connection open\r\n");
+       else if (pdata != -1) {
+               printf("     in Passive mode");
+               sin = &pasv_addr;
+               goto printaddr;
+       } else if (usedefault == 0) {
+               printf("     PORT");
+               sin = &data_dest;
+printaddr:
+               a = (u_char *) &sin->sin_addr;
+               p = (u_char *) &sin->sin_port;
+#define UC(b) (((int) b) & 0xff)
+               printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
+                       UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+#undef UC
+       } else
+               printf("     No data connection\r\n");
+       reply(211, "End of status");
+}
+
+void
+fatal(s)
+       char *s;
+{
+
+       reply(451, "Error in server: %s\n", s);
+       reply(221, "Closing connection due to server error.");
+       dologout(0);
+       /* NOTREACHED */
+}
+
+void
+#if __STDC__
+reply(int n, const char *fmt, ...)
+#else
+reply(n, fmt, va_alist)
+       int n;
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)printf("%d ", n);
+       (void)vprintf(fmt, ap);
+       (void)printf("\r\n");
+       (void)fflush(stdout);
+       if (debug) {
+               syslog(LOG_DEBUG, "<--- %d ", n);
+               vsyslog(LOG_DEBUG, fmt, ap);
+       }
+}
+
+void
+#if __STDC__
+lreply(int n, const char *fmt, ...)
+#else
+lreply(n, fmt, va_alist)
+       int n;
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)printf("%d- ", n);
+       (void)vprintf(fmt, ap);
+       (void)printf("\r\n");
+       (void)fflush(stdout);
+       if (debug) {
+               syslog(LOG_DEBUG, "<--- %d- ", n);
+               vsyslog(LOG_DEBUG, fmt, ap);
+       }
+}
+
+static void
+ack(s)
+       char *s;
+{
+
+       reply(250, "%s command successful.", s);
+}
+
+void
+nack(s)
+       char *s;
+{
+
+       reply(502, "%s command not implemented.", s);
+}
+
+/* ARGSUSED */
+void
+yyerror(s)
+       char *s;
+{
+       char *cp;
+
+       if (cp = strchr(cbuf,'\n'))
+               *cp = '\0';
+       reply(500, "'%s': command not understood.", cbuf);
+}
+
+void
+delete(name)
+       char *name;
+{
+       struct stat st;
+
+       LOGCMD("delete", name);
+       if (stat(name, &st) < 0) {
+               perror_reply(550, name);
+               return;
+       }
+       if ((st.st_mode&S_IFMT) == S_IFDIR) {
+               if (rmdir(name) < 0) {
+                       perror_reply(550, name);
+                       return;
+               }
+               goto done;
+       }
+       if (unlink(name) < 0) {
+               perror_reply(550, name);
+               return;
+       }
+done:
+       ack("DELE");
+}
+
+void
+cwd(path)
+       char *path;
+{
+
+       if (chdir(path) < 0)
+               perror_reply(550, path);
+       else
+               ack("CWD");
+}
+
+void
+makedir(name)
+       char *name;
+{
+
+       LOGCMD("mkdir", name);
+       if (mkdir(name, 0777) < 0)
+               perror_reply(550, name);
+       else
+               reply(257, "MKD command successful.");
+}
+
+void
+removedir(name)
+       char *name;
+{
+
+       LOGCMD("rmdir", name);
+       if (rmdir(name) < 0)
+               perror_reply(550, name);
+       else
+               ack("RMD");
+}
+
+void
+pwd()
+{
+       char path[MAXPATHLEN];
+
+       if (getcwd(path, sizeof(path)) == (char *)NULL)
+               reply(550, "%s.", path);
+       else
+               reply(257, "\"%s\" is current directory.", path);
+}
+
+char *
+renamefrom(name)
+       char *name;
+{
+       struct stat st;
+
+       if (stat(name, &st) < 0) {
+               perror_reply(550, name);
+               return ((char *)0);
+       }
+       reply(350, "File exists, ready for destination name");
+       return (name);
+}
+
+void
+renamecmd(from, to)
+       char *from, *to;
+{
+
+       LOGCMD2("rename", from, to);
+       if (rename(from, to) < 0)
+               perror_reply(550, "rename");
+       else
+               ack("RNTO");
+}
+
+static void
+dolog(sin)
+       struct sockaddr_in *sin;
+{
+       struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr,
+               sizeof(struct in_addr), AF_INET);
+
+       if (hp)
+               (void) strncpy(remotehost, hp->h_name, sizeof(remotehost));
+       else
+               (void) strncpy(remotehost, inet_ntoa(sin->sin_addr),
+                   sizeof(remotehost));
+#ifdef SETPROCTITLE
+       snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
+       setproctitle("%s", proctitle);
+#endif /* SETPROCTITLE */
+
+       if (logging)
+               syslog(LOG_INFO, "connection from %s", remotehost);
+}
+
+/*
+ * Record logout in wtmp file
+ * and exit with supplied status.
+ */
+void
+dologout(status)
+       int status;
+{
+       /*
+       * Prevent reception of SIGURG from resulting in a resumption
+       * back to the main program loop.
+       */
+       transflag = 0;
+
+       if (logged_in) {
+               (void) seteuid((uid_t)0);
+               logwtmp(ttyline, "", "");
+       }
+       /* beware of flushing buffers after a SIGPIPE */
+       _exit(status);
+}
+
+static void
+myoob(signo)
+       int signo;
+{
+       char *cp;
+
+       /* only process if transfer occurring */
+       if (!transflag)
+               return;
+       cp = tmpline;
+       if (getline(cp, 7, stdin) == NULL) {
+               reply(221, "You could at least say goodbye.");
+               dologout(0);
+       }
+       upper(cp);
+       if (strcmp(cp, "ABOR\r\n") == 0) {
+               tmpline[0] = '\0';
+               reply(426, "Transfer aborted. Data connection closed.");
+               reply(226, "Abort successful");
+               longjmp(urgcatch, 1);
+       }
+       if (strcmp(cp, "STAT\r\n") == 0) {
+               if (file_size != (off_t) -1)
+                       reply(213, "Status: %qd of %qd bytes transferred",
+                           byte_count, file_size);
+               else
+                       reply(213, "Status: %qd bytes transferred", byte_count);
+       }
+}
+
+/*
+ * Note: a response of 425 is not mentioned as a possible response to
+ *     the PASV command in RFC959. However, it has been blessed as
+ *     a legitimate response by Jon Postel in a telephone conversation
+ *     with Rick Adams on 25 Jan 89.
+ */
+void
+passive()
+{
+       int len;
+       char *p, *a;
+
+       pdata = socket(AF_INET, SOCK_STREAM, 0);
+       if (pdata < 0) {
+               perror_reply(425, "Can't open passive connection");
+               return;
+       }
+       pasv_addr = ctrl_addr;
+       pasv_addr.sin_port = 0;
+       (void) seteuid((uid_t)0);
+       if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) {
+               (void) seteuid((uid_t)pw->pw_uid);
+               goto pasv_error;
+       }
+       (void) seteuid((uid_t)pw->pw_uid);
+       len = sizeof(pasv_addr);
+       if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
+               goto pasv_error;
+       if (listen(pdata, 1) < 0)
+               goto pasv_error;
+       a = (char *) &pasv_addr.sin_addr;
+       p = (char *) &pasv_addr.sin_port;
+
+#define UC(b) (((int) b) & 0xff)
+
+       reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
+               UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+       return;
+
+pasv_error:
+       (void) close(pdata);
+       pdata = -1;
+       perror_reply(425, "Can't open passive connection");
+       return;
+}
+
+/*
+ * Generate unique name for file with basename "local".
+ * The file named "local" is already known to exist.
+ * Generates failure reply on error.
+ */
+static char *
+gunique(local)
+       char *local;
+{
+       static char new[MAXPATHLEN];
+       struct stat st;
+       int count;
+       char *cp;
+
+       cp = strrchr(local, '/');
+       if (cp)
+               *cp = '\0';
+       if (stat(cp ? local : ".", &st) < 0) {
+               perror_reply(553, cp ? local : ".");
+               return ((char *) 0);
+       }
+       if (cp)
+               *cp = '/';
+       (void) strcpy(new, local);
+       cp = new + strlen(new);
+       *cp++ = '.';
+       for (count = 1; count < 100; count++) {
+               (void)sprintf(cp, "%d", count);
+               if (stat(new, &st) < 0)
+                       return (new);
+       }
+       reply(452, "Unique file name cannot be created.");
+       return (NULL);
+}
+
+/*
+ * Format and send reply containing system error number.
+ */
+void
+perror_reply(code, string)
+       int code;
+       char *string;
+{
+
+       reply(code, "%s: %s.", string, strerror(errno));
+}
+
+static char *onefile[] = {
+       "",
+       0
+};
+
+void
+send_file_list(whichf)
+       char *whichf;
+{
+       struct stat st;
+       DIR *dirp = NULL;
+       struct dirent *dir;
+       FILE *dout = NULL;
+       char **dirlist, *dirname;
+       int simple = 0;
+       int freeglob = 0;
+       glob_t gl;
+
+       if (strpbrk(whichf, "~{[*?") != NULL) {
+               int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+               memset(&gl, 0, sizeof(gl));
+               freeglob = 1;
+               if (glob(whichf, flags, 0, &gl)) {
+                       reply(550, "not found");
+                       goto out;
+               } else if (gl.gl_pathc == 0) {
+                       errno = ENOENT;
+                       perror_reply(550, whichf);
+                       goto out;
+               }
+               dirlist = gl.gl_pathv;
+       } else {
+               onefile[0] = whichf;
+               dirlist = onefile;
+               simple = 1;
+       }
+
+       if (setjmp(urgcatch)) {
+               transflag = 0;
+               goto out;
+       }
+       while (dirname = *dirlist++) {
+               if (stat(dirname, &st) < 0) {
+                       /*
+                        * If user typed "ls -l", etc, and the client
+                        * used NLST, do what the user meant.
+                        */
+                       if (dirname[0] == '-' && *dirlist == NULL &&
+                           transflag == 0) {
+                               retrieve("/bin/ls %s", dirname);
+                               goto out;
+                       }
+                       perror_reply(550, whichf);
+                       if (dout != NULL) {
+                               (void) fclose(dout);
+                               transflag = 0;
+                               data = -1;
+                               pdata = -1;
+                       }
+                       goto out;
+               }
+
+               if (S_ISREG(st.st_mode)) {
+                       if (dout == NULL) {
+                               dout = dataconn("file list", (off_t)-1, "w");
+                               if (dout == NULL)
+                                       goto out;
+                               transflag++;
+                       }
+                       fprintf(dout, "%s%s\n", dirname,
+                               type == TYPE_A ? "\r" : "");
+                       byte_count += strlen(dirname) + 1;
+                       continue;
+               } else if (!S_ISDIR(st.st_mode))
+                       continue;
+
+               if ((dirp = opendir(dirname)) == NULL)
+                       continue;
+
+               while ((dir = readdir(dirp)) != NULL) {
+                       char nbuf[MAXPATHLEN];
+
+                       if (dir->d_name[0] == '.' && dir->d_namlen == 1)
+                               continue;
+                       if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
+                           dir->d_namlen == 2)
+                               continue;
+
+                       sprintf(nbuf, "%s/%s", dirname, dir->d_name);
+
+                       /*
+                        * We have to do a stat to insure it's
+                        * not a directory or special file.
+                        */
+                       if (simple || (stat(nbuf, &st) == 0 &&
+                           S_ISREG(st.st_mode))) {
+                               if (dout == NULL) {
+                                       dout = dataconn("file list", (off_t)-1,
+                                               "w");
+                                       if (dout == NULL)
+                                               goto out;
+                                       transflag++;
+                               }
+                               if (nbuf[0] == '.' && nbuf[1] == '/')
+                                       fprintf(dout, "%s%s\n", &nbuf[2],
+                                               type == TYPE_A ? "\r" : "");
+                               else
+                                       fprintf(dout, "%s%s\n", nbuf,
+                                               type == TYPE_A ? "\r" : "");
+                               byte_count += strlen(nbuf) + 1;
+                       }
+               }
+               (void) closedir(dirp);
+       }
+
+       if (dout == NULL)
+               reply(550, "No files found.");
+       else if (ferror(dout) != 0)
+               perror_reply(550, "Data connection");
+       else
+               reply(226, "Transfer complete.");
+
+       transflag = 0;
+       if (dout != NULL)
+               (void) fclose(dout);
+       data = -1;
+       pdata = -1;
+out:
+       if (freeglob) {
+               freeglob = 0;
+               globfree(&gl);
+       }
+}
+
+#ifdef SETPROCTITLE
+/*
+ * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
+ * Warning, since this is usually started from inetd.conf, it often doesn't
+ * have much of an environment or arglist to overwrite.
+ */
+void
+#if __STDC__
+setproctitle(const char *fmt, ...)
+#else
+setproctitle(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       int i;
+       va_list ap;
+       char *p, *bp, ch;
+       char buf[LINE_MAX];
+
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)vsnprintf(buf, sizeof(buf), fmt, ap);
+
+       /* make ps print our process name */
+       p = Argv[0];
+       *p++ = '-';
+
+       i = strlen(buf);
+       if (i > LastArgv - p - 2) {
+               i = LastArgv - p - 2;
+               buf[i] = '\0';
+       }
+       bp = buf;
+       while (ch = *bp++)
+               if (ch != '\n' && ch != '\r')
+                       *p++ = ch;
+       while (p < LastArgv)
+               *p++ = ' ';
+}
+#endif /* SETPROCTITLE */
+#pragma CC_OPT_RESTORE
diff --git a/ftpd.tproj/logwtmp.c b/ftpd.tproj/logwtmp.c
new file mode 100644 (file)
index 0000000..cca4d26
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)logwtmp.c  8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include "extern.h"
+
+static int fd = -1;
+
+/*
+ * Modified version of logwtmp that holds wtmp file open
+ * after first call, for use with ftp (which may chroot
+ * after login, but before logout).
+ */
+void
+logwtmp(line, name, host)
+       char *line, *name, *host;
+{
+       struct utmp ut;
+       struct stat buf;
+
+       if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
+               return;
+       if (fstat(fd, &buf) == 0) {
+               (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+               (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+               (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+               (void)time(&ut.ut_time);
+               if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
+                   sizeof(struct utmp))
+                       (void)ftruncate(fd, buf.st_size);
+       }
+}
diff --git a/ftpd.tproj/pathnames.h b/ftpd.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..56868c4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ */
+
+#include <paths.h>
+
+#define        _PATH_FTPUSERS          "/etc/ftpusers"
+#define        _PATH_FTPWELCOME        "/etc/ftpwelcome"
+#define        _PATH_FTPLOGINMESG      "/etc/motd"
diff --git a/ftpd.tproj/popen.c b/ftpd.tproj/popen.c
new file mode 100644 (file)
index 0000000..dab3d3f
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)popen.c    8.3 (Berkeley) 4/6/94";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <glob.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+/*
+ * Special version of popen which avoids call to shell.  This ensures noone
+ * may create a pipe to a hidden program as a side effect of a list or dir
+ * command.
+ */
+static int *pids;
+static int fds;
+
+FILE *
+ftpd_popen(program, type)
+       char *program, *type;
+{
+       char *cp;
+       FILE *iop;
+       int argc, gargc, pdes[2], pid;
+       char **pop, *argv[100], *gargv[1000];
+
+       if (*type != 'r' && *type != 'w' || type[1])
+               return (NULL);
+
+       if (!pids) {
+               if ((fds = getdtablesize()) <= 0)
+                       return (NULL);
+               if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
+                       return (NULL);
+               memset(pids, 0, fds * sizeof(int));
+       }
+       if (pipe(pdes) < 0)
+               return (NULL);
+
+       /* break up string into pieces */
+       for (argc = 0, cp = program;; cp = NULL)
+               if (!(argv[argc++] = strtok(cp, " \t\n")))
+                       break;
+
+       /* glob each piece */
+       gargv[0] = argv[0];
+       for (gargc = argc = 1; argv[argc]; argc++) {
+               glob_t gl;
+               int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+               memset(&gl, 0, sizeof(gl));
+               if (glob(argv[argc], flags, NULL, &gl))
+                       gargv[gargc++] = strdup(argv[argc]);
+               else
+                       for (pop = gl.gl_pathv; *pop; pop++)
+                               gargv[gargc++] = strdup(*pop);
+               globfree(&gl);
+       }
+       gargv[gargc] = NULL;
+
+       iop = NULL;
+       switch(pid = vfork()) {
+       case -1:                        /* error */
+               (void)close(pdes[0]);
+               (void)close(pdes[1]);
+               goto pfree;
+               /* NOTREACHED */
+       case 0:                         /* child */
+               if (*type == 'r') {
+                       if (pdes[1] != STDOUT_FILENO) {
+                               dup2(pdes[1], STDOUT_FILENO);
+                               (void)close(pdes[1]);
+                       }
+                       dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */
+                       (void)close(pdes[0]);
+               } else {
+                       if (pdes[0] != STDIN_FILENO) {
+                               dup2(pdes[0], STDIN_FILENO);
+                               (void)close(pdes[0]);
+                       }
+                       (void)close(pdes[1]);
+               }
+               execv(gargv[0], gargv);
+               _exit(1);
+       }
+       /* parent; assume fdopen can't fail...  */
+       if (*type == 'r') {
+               iop = fdopen(pdes[0], type);
+               (void)close(pdes[1]);
+       } else {
+               iop = fdopen(pdes[1], type);
+               (void)close(pdes[0]);
+       }
+       pids[fileno(iop)] = pid;
+
+pfree: for (argc = 1; gargv[argc] != NULL; argc++)
+               free(gargv[argc]);
+
+       return (iop);
+}
+
+int
+ftpd_pclose(iop)
+       FILE *iop;
+{
+       int fdes, omask, status;
+       pid_t pid;
+
+       /*
+        * pclose returns -1 if stream is not associated with a
+        * `popened' command, or, if already `pclosed'.
+        */
+       if (pids == 0 || pids[fdes = fileno(iop)] == 0)
+               return (-1);
+       (void)fclose(iop);
+       omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
+       while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
+               continue;
+       (void)sigsetmask(omask);
+       pids[fdes] = 0;
+       if (pid < 0)
+               return (pid);
+       if (WIFEXITED(status))
+               return (WEXITSTATUS(status));
+       return (1);
+}
diff --git a/ftpd.tproj/vers.c b/ftpd.tproj/vers.c
new file mode 100644 (file)
index 0000000..ee00fa9
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+/*static char sccsid[] = "from: @(#)vers.c     5.1 (Berkeley) 6/24/90";*/
+static char rcsid[] = "$Id: vers.c,v 1.1.1.1 1999/05/02 03:57:40 wsanchez Exp $";
+#endif /* not lint */
+
+char version[] = "Version 5.60";
diff --git a/identd.tproj/CREDITS b/identd.tproj/CREDITS
new file mode 100644 (file)
index 0000000..c117a03
--- /dev/null
@@ -0,0 +1,52 @@
+Credits go to (I've probably forgot someone - please don't hesitate
+to tell me!) for helping making Pidentd what it is:
+
+Casper Dik <casper@fwi.uva.nl>, Math & CS Faculty, U. of Amsterdam, NL
+       (Added support for SunOS 5 (Solaris 2))
+
+Dave Shield <D.T.Shield@compsci.liverpool.ac.uk>, CS Dept. Liverpool U., UK
+       (Added support for HP9K HPUX 8.*)
+
+Jan L. Peterson <jlp@phred.math.byu.edu>, Math Dept. BYU, USA
+       (Added support for MIPS RISC/os and fixed a few other things)
+
+Fletcher Mattox <fletcher@cs.utexas.edu>, University of Texas, USA
+       (Added support for HP9K HP-UX 7.*)
+
+Mark Monnin <mgrmem@nextwork.rose-hulman.edu>, Rose-Hulman Inst. of Tech, USA
+       (Added support for DEC Ultrix 4.*)
+
+Simon Leinen <simon@lia.di.epfl.ch>, Switzerland
+       (Added support for Silicon Graphics IRIX 4.*)
+
+Frank Maas <maas@dutiws.tudelft.nl>, Delft Univ. of Technology, The Netherlands
+       (Added support for Sequent Dynix 3.*)
+
+Andrew Herbert <andrewh@molly.cs.monash.edu.au>, Monash University, Australia
+       (Added support for System V/Release 4)
+
+David Bennet <ddt@gu.uwa.edu.au>, Australia
+       (Added support for 386BSD)
+
+Fishman M. Shmuel <fms@ccgr.technion.ac.il>, Technion Inst. of Tech., Israel
+       (Added support for Convex & 4.3BSDtahoe (then heavily hacked by me))
+
+Bradley E. Smith <brad@bradley.bradley.edu>, Bradley University, USA
+       (Added support for AT&T's own version of SVR4)
+
+RenE J.V. Bertin <bertin@neuretD.biol.ruu.nl>, Uni. of Utrecht, The Netherlands
+       (Added support for Apple A/UX 2.*)
+
+Douglas Lee Schales <Doug.Schales@sc.tamu.edu>, Texas A&M University, USA
+       (Added support for Cray UNICOS 6.*)
+
+Don Hazlewood <haz@dali.math.swt.edu>, SW Texas State U., USA
+       (Added support for A/UX 3.*)
+
+ Nigel Metheringham <nigelm@ohm.york.ac.uk>, University of York, UK
+       (Added support for NeXT, SunOS 3.*, corrections for MIPS)
+
+----------------------------------------------------------------------------
+Peter Eriksson <pen@lysator.liu.se>, Lysator, Linkoping University, Sweden.
+       (Original code for Sun SunOS 4.* and Sequent Dynix 2.*)
+
diff --git a/identd.tproj/Makefile b/identd.tproj/Makefile
new file mode 100644 (file)
index 0000000..b8d220f
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = identd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = error.h identd.h xpaths.h
+
+CFILES = config.c identd.c netbsd.c parse.c proxy.c version.c
+
+OTHERSRCS = CREDITS Makefile.dist README identd.8 Makefile.preamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/identd.tproj/Makefile.dist b/identd.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..fad1caa
--- /dev/null
@@ -0,0 +1,10 @@
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:57:40 wsanchez Exp $
+
+PROG=  identd
+SRCS=  config.c identd.c netbsd.c parse.c proxy.c version.c
+MAN8=  identd.0
+
+LDADD= -lkvm
+DPADD= ${LIBKVM}
+
+.include <bsd.prog.mk>
diff --git a/identd.tproj/Makefile.preamble b/identd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/identd.tproj/PB.project b/identd.tproj/PB.project
new file mode 100644 (file)
index 0000000..b6dd3a8
--- /dev/null
@@ -0,0 +1,40 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (error.h, identd.h, xpaths.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (config.c, identd.c, netbsd.c, parse.c, proxy.c, version.c); 
+        OTHER_SOURCES = (CREDITS, Makefile.dist, README, identd.8, Makefile.preamble); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = identd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/identd.tproj/README b/identd.tproj/README
new file mode 100644 (file)
index 0000000..f1e1d3b
--- /dev/null
@@ -0,0 +1,129 @@
+                            pidentd
+
+     ("Peter's Ident Daemon" or is it "Portable Ident Daemon"?)
+
+               Peter Eriksson <pen@lysator.liu.se>
+
+
+This program is released into the public domain and can be used by
+anyone who wants to. Vendors may include it into their distributions
+if they want to without any restrictions. (Although it would be nice
+to be notified by email if someone decides to do that, and/or a note
+somewhere about who wrote this program. Like in the man-page or so.. :-)
+
+This is a program that implements the RFC1413 identification server. It
+was very much inspired by Dan Bernstein's original 'authd' (but unlike
+that program doesn't use 'netstat' to get some of the information) It
+uses the kernel information directly.  (And is due to that fact a lot
+faster). Dan has now written another version of the 'authd' daemon that
+uses his 'kstuff' to read the kernel information. Unlike that daemon,
+this will use only normally available kernel access functions (and is due
+to that more limited in the different machines it support). Please note
+that this daemon used to be called pauthd but has changed name to better
+reflect what it does (and to conform to the new RFC).
+
+This daemon has been tested on the following machines/OS (please report
+to me if you've tested a newer version, or if your machine/OS isn't among
+the ones below):
+
+Machine                        Operating System        Pidentd version
+----------------------  ----------------------  --------------------------
+  Sequent Balance        Dynix 3.0.14            2.1beta.12
+  Sequent Symmetry        Dynix 3.1.2            2.1beta.3
+  Sun 3/50                SunOS 3.5               2.1beta.8.1           (3)
+  Sun 386i               SunOS 4.0.2             1.9beta
+  Sun 2/120              SunOS 4.0.3             2.1beta.10
+  Sun 3/280              SunOS 4.1.1             2.1beta.12
+  Sun 4/380              SunOS 4.1.3             2.1beta.12
+  Sun SS1/41             SunOS 5.1               2.1beta.11
+  HP 9000/375             HP-UX 7.0              2.1beta.10.1          (1)
+  HP 9000/300            HP-UX 8.0               2.1beta.12
+  HP 9000/340            HP-UX 8.0               2.1beta.10.1
+  HP 9000/360            HP-UX 8.0               2.1beta.10.1
+  HP 9000/710             HP-UX 8.07              2.1beta.10.1
+  HP 9000/720             HP-UX 8.07             2.1beta.10.1
+  HP 9000/715             HP-UX 9.0               2.1beta.9.1
+  HP 9000/827             HP-UX 8.02              2.1beta.8.1
+  HP 9000/834            HP-UX 7.0               2.0beta.4
+  HP 9000/835            HP-UX 8.00              2.1beta.10.1
+  MIPS                   RISC/OS 4.5x            2.1beta.8.1
+  DECstation 2100         Ultrix 4.2-96           2.1beta.2            (2)
+  DECstation 5000/133     Ultrix 4.2              2.1beta.9.1           (2) [?]
+  DEC VAXstation 2000    Ultrix-32 3.1           2.1beta.12            (2) [?]
+  DEC VAX vs3520          Ultrix 3.0              2.1beta.9.1           (2) [?]
+  DEC VAX 11/780         4.3BSD Reno             2.1beta.12            (2)
+  i486-PC                UHC SVR4 2.0            2.0beta.4             (2)
+  i486-PC                Dell SVR4 2.2           2.0beta.4             (2)
+  i486-PC                ESIX SVR4 4.0.4         2.1beta.2             (2)
+  i486-PC                386BSD 0.1              2.1beta.3             (2)
+  Cray                   UNICOS 6.0.12           2.1beta.7
+  NeXT                    NeXTSTEP 2.1            2.1beta.9.1          (3)
+  NeXT                    NeXTSTEP 3.0            2.1beta.9.1          (3)
+  Pyramid 90x            dualPort OSx 4.1        2.1beta.12
+  Silicon Graphics       IRIX 4                  2.1beta.10
+
+Notes:
+       1) HP-UX 7.0 doesn't support running streams based services from
+          Inetd with the "wait" option (and the "-w" flag to Pidentd).
+
+          It also has problems with starting stuff as user "sys" from Inetd.
+          (It doesn't correctly set the group id to "sys") so I suggest you
+           either starts it as user "root" and use the "-u" and "-g" flags
+           to setuid and setgid itself to user "sys", group "sys", or do a
+          'chgrp sys in.identd' and then a 'chmod g+s in.identd' and start
+          it as user "sys" from Inetd.
+
+       2) These systems also doesn't support running streams based
+          services from Inetd with the "wait" option. 
+          
+       3) See notes in the READMEs/README.<machine-type> specific files.
+          
+
+Please let me know if you find any bugs, or have ported it to other
+machines (and care to share the changes with me and the world!).
+
+See the manual page for information about the various command line
+options that are available.
+
+NOTE: One should NOT use the -d option when using it for normal use!
+
+If you intend to create or modify daemons that use the IDENT protocol
+then you may wish to get the "libident" library that contains some
+functions to implement the client side of this protocol. It is available
+as "libident-*.tar.Z" in "pub/ident/libs" at "ftp.lysator.liu.se".
+
+There is a mailing list for users of the IDENT(RFC1413)/TAP protocol called
+'ident-users@lysator.liu.se' that you may want to consider joining.
+Send mail to the address 'ident-users-request@lysator.liu.se' to 
+join it. This list is intended for generic discussions on using this
+protocol and it's associated tools.
+
+If you only want to receive news about new (non-alpha/beta) releases of
+Pidentd then you can join the 'ident-announce@lysator.liu.se' mailing
+list. Send mail to the address 'ident-announce-request@lysator.liu.se' to 
+join it. No discussions will take place on this list.
+
+I also run a small mailing list for people who wants to act as testers
+of new alpha/beta-versions of Pidentd. If you wish to join, please send
+mail to the address 'pidentd-testers-request@lysator.liu.se'. (I can always
+use more testers, so don't hesitate :-)
+
+It's a human (namely me :-) that reads the letters sent to *-request.
+Please include the full email address to which to wish to have the
+letters sent.
+
+I'm grateful for success/failure stories about installing/compiling this
+daemon...
+
+Information of interrest:
+
+  1. Machine and operating system type and version.
+  2. Command line flags.
+  3. Inetd.conf configuration.
+  4. Did it work, or not. And if not - what did it report to the
+     syslog file? (You'll have to add the "-l" option and probably
+     reconfigure your Syslogd). If you use the "-d" option then
+     you can see a verbose error if you Telnet into it directly and
+     send it a query manually. (See the INSTALL file for more information).
+
+/Peter Eriksson <pen@lysator.liu.se>, 5 April 1993
diff --git a/identd.tproj/config.c b/identd.tproj/config.c
new file mode 100644 (file)
index 0000000..19eec4c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: config.c,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $
+**
+** config.c                         This file handles the config file
+**
+** This program is in the public domain and may be used freely by anyone
+** who wants to. 
+**
+** Last update: 6 Dec 1992
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "error.h"
+#include "identd.h"
+#include "xpaths.h"
+
+
+int parse_config(path, silent_flag)
+  char *path;
+  int silent_flag;
+{
+  FILE *fp;
+
+  if (!path)
+    path = PATH_CONFIG;
+  
+  fp = fopen(path, "r");
+  if (!fp)
+  {
+    if (silent_flag)
+      return 0;
+
+    ERROR1("error opening %s", path);
+  }
+
+  /*
+  ** Code should go here to parse the config file data.
+  ** For now we just ignore the contents...
+  */
+  
+  
+  fclose(fp);
+  return 0;
+}
diff --git a/identd.tproj/error.h b/identd.tproj/error.h
new file mode 100644 (file)
index 0000000..d5f1990
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: error.h,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $
+**
+** error.h                                               Error handling macros
+**
+** This program is in the public domain and may be used freely by anyone
+** who wants to. 
+**
+** Last update: 19 Aug 1992
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#ifndef __ERROR_H__
+#define __ERROR_H__
+
+#include <syslog.h>
+
+#define ERROR(fmt) \
+    ((syslog_flag ? (syslog(LOG_ERR, fmt),0) : 0), \
+     (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
+                           lport, fport), \
+                   fprintf(stderr, fmt), perror(": "), 0) : \
+      (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
+     fflush(stdout), fflush(stderr), exit(1), 0)
+
+
+#define ERROR1(fmt,v1) \
+    ((syslog_flag ? (syslog(LOG_ERR, fmt, v1),0) : 0), \
+     (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
+                           lport, fport), \
+                   fprintf(stderr, fmt, v1), perror(": "), 0) : \
+      (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
+     fflush(stdout), fflush(stderr), exit(1), 0)
+
+#define ERROR2(fmt,v1,v2) \
+    ((syslog_flag ? (syslog(LOG_ERR, fmt, v1, v2),0) : 0), \
+     (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
+                           lport, fport), \
+                   fprintf(stderr, fmt, v1, v2), perror(": "), 0) : \
+      (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
+     fflush(stdout), fflush(stderr), exit(1), 0)
+
+#endif
diff --git a/identd.tproj/identd.8 b/identd.tproj/identd.8
new file mode 100644 (file)
index 0000000..4bf839c
--- /dev/null
@@ -0,0 +1,238 @@
+.\" @(#)identd.8 1.9 92/02/11 Lysator
+.\" Copyright (c) 1992 Peter Eriksson, Lysator, Linkoping University.
+.\" This software has been released into the public domain.
+.\"
+.\"    $Id: identd.8,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $
+.\"
+.TH IDENTD 8 "27 May 1992"
+.SH NAME
+identd \- TCP/IP IDENT protocol server
+.SH SYNOPSIS
+.B identd
+.RB [ \-i | \-w | \-b ]
+.RB [ \-t<seconds> ]
+.RB [ \-u<uid> ]
+.RB [ \-g<gid> ]
+.RB [ \-p<port> ]
+.RB [ \-a<address> ]
+.RB [ \-c<charset> ]
+.RB [ \-n ]
+.RB [ \-o ]
+.RB [ \-e ]
+.RB [ \-l ]
+.RB [ \-V ]
+.RB [ \-v ]
+.RB [ \-m ]
+.RB [ \-N ]
+.RB [ \-d ]
+.RB [ kernelfile [ kmemfile ] ]
+.SH DESCRIPTION
+.IX "identd daemon" "" \fLidentd\fP daemon"
+.B identd
+is a server which implements the
+.SM TCP/IP
+proposed standard
+.SM IDENT
+user identification protocol as specified in the
+.SM RFC\s0 1413
+document.
+.PP
+.B identd
+operates by looking up specific
+.SM TCP/IP
+connections and returning the user name of the
+process owning the connection.
+.SH ARGUMENTS
+The
+.B -i
+flag, which is the default mode, should be used when starting the
+daemon from
+.B inetd
+with the "nowait" option in the
+.B /etc/inetd.conf
+file. Use of this mode will make
+.B inetd
+start one
+.B identd
+daemon for each connection request.
+.PP
+The
+.B -w
+flag should be used when starting the daemon from
+.B inetd
+with the "wait" option in the
+.B /etc/inetd.conf
+file . This is the prefered mode of
+operation since that will start a copy of
+.B identd
+at the first connection request and then
+.B identd
+will handle subsequent requests
+without having to do the nlist lookup in the kernel file for
+every request as in the
+.B -i
+mode above. The
+.B identd
+daemon will run either forever, until a bug
+makes it crash or a timeout, as specified by the
+.B -t
+flag, occurs.
+.PP
+The
+.B -b
+flag can be used to make the daemon run in standalone mode without
+the assistance from
+.B inetd.
+This mode is the least prefered mode since
+a bug or any other fatal condition in the server will make it terminate
+and it will then have to be restarted manually. Other than that is has the
+same advantage as the
+.B -w
+mode in that it parses the nlist only once.
+.PP
+The
+.B -t<seconds>
+option is used to specify the timeout limit. This is the number
+of seconds a server started with the
+.B -w
+flag will wait for new connections before terminating. The server is
+automatically restarted by
+.B inetd
+whenever a new connection is requested
+if it has terminated. A suitable value for this is 120 (2 minutes), if
+used. It defaults to no timeout (ie, will wait forever, or until a
+fatal condition occurs in the server).
+.PP
+The
+.B -u<uid>
+option is used to specify a user id number which the
+.B ident
+server should
+switch to after binding itself to the
+.SM TCP/IP
+port if using the
+.B -b
+mode of operation.
+.PP
+The
+.B -g<gid>
+option is used to specify a group id number which the
+.B ident
+server should
+switch to after binding itself to the
+.SM TCP/IP
+port if using the
+.B -b
+mode of operation.
+.PP
+The
+.B -p<port>
+option is used to specify an alternative port number to bind to if using
+the
+.B -b
+mode of operation. It can be specified by name or by number. Defaults to the
+.SM IDENT
+port (113).
+.PP
+The
+.B -a<address>
+option is used to specify the local address to bind the socket to if using
+the
+.B -b
+mode of operation. Can only be specified by IP address and not by domain
+name. Defaults to the 
+.SM INADDR_ANY
+address which normally means all local addresses.
+.PP
+The 
+.B -V
+flag makes
+.B identd
+display the version number and the exit.
+.PP
+The
+.B -l
+flag tells
+.B identd
+to use the System logging daemon
+.B syslogd
+for logging purposes.
+.PP
+The 
+.B -v
+flag causes
+.B identd
+to log every request made, if the use of
+.B syslogd
+is enabled.
+.PP
+The
+.B -o
+flag tells
+.B identd
+to not reveal the operating system type it is run on and to instead
+always return "OTHER".
+.PP
+The
+.B -e
+flag tells
+.B identd
+to always return "UNKNOWN-ERROR" instead of the "NO-USER" or
+"INVALID-PORT" errors.
+.PP
+The
+.B -c<charset>
+flags tells
+.B identd
+to add the optional (according to the IDENT protocol) character set
+designator to the reply generated. <charset> should be a valid character
+set as described in the MIME RFC in upper case characters.
+.PP
+The
+.B -n
+flags tells
+.B identd
+to always return user numbers instead of user names if you wish to
+keep the user names a secret.
+.PP
+The
+.B -N
+flag makes
+.B identd
+check for a file ".noident" in each homedirectory for a user which the
+daemon is about to return the user name for. It that file exists then the
+daemon will give the error
+.B HIDDEN-USER
+instead of the normal USERID response. 
+.PP
+.B -m
+flag makes
+.B identd
+use a mode of operation that will allow multiple requests to be
+processed per session. Each request is specified one per line and
+the responses will be returned one per line. The connection will not
+be closed until the connecting part closes it's end of the line.
+PLEASE NOTE THAT THIS MODE VIOLATES THE PROTOCOL SPECIFICATION AS
+IT CURRENTLY STANDS.
+.PP
+The
+.B -d
+flag enables some debugging code that normally should NOT
+be enabled since that breaks the protocol and may reveal information
+that should not be available to outsiders.
+.PP
+.B kernelfile
+defaults to the normally running kernel file.
+.PP
+.B kmemfile
+defaults to the memory space of the normally running kernel.
+.SH SEE ALSO
+.BR inetd.conf (5)
+.SH BUGS
+The handling of fatal errors could be better.
+.PP
+If the
+.B -N
+flag is specified and a user's ".noident" file is not accessible,
+then ident information regarding that user will be returned
+if requested.
diff --git a/identd.tproj/identd.c b/identd.tproj/identd.c
new file mode 100644 (file)
index 0000000..7380de1
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: identd.c,v 1.1.1.2 2000/01/11 01:48:48 wsanchez Exp $
+**
+** identd.c                       A TCP/IP link identification protocol server
+**
+** This program is in the public domain and may be used freely by anyone
+** who wants to. 
+**
+** Last update: 22 April 1993
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#if defined(IRIX) || defined(SVR4) || defined(__APPLE__) || defined(__NetBSD__)
+#  define SIGRETURN_TYPE void
+#  define SIGRETURN_TYPE_IS_VOID
+#else
+#  define SIGRETURN_TYPE int
+#endif
+
+#ifdef SVR4
+#  define STRNET
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifndef _AUX_SOURCE
+#  include <sys/file.h>
+#endif
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <pwd.h>
+#include <grp.h>
+
+#include <netinet/in.h>
+
+#ifndef HPUX7
+#  include <arpa/inet.h>
+#endif
+
+#if defined(MIPS) || defined(BSD43)
+extern int errno;
+#endif
+
+#include "identd.h"
+#include "error.h"
+
+/* Antique unixes do not have these things defined... */
+#ifndef FD_SETSIZE
+#  define FD_SETSIZE 256
+#endif
+
+#ifndef FD_SET
+#  ifndef NFDBITS
+#    define NFDBITS    (sizeof(int) * NBBY)  /* bits per mask */
+#  endif
+#  define FD_SET(n, p)  ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#endif
+
+#ifndef FD_ZERO
+#  define FD_ZERO(p)        bzero((char *)(p), sizeof(*(p)))
+#endif
+
+extern char *version;
+
+extern void *calloc();
+extern void *malloc();
+
+
+char *path_unix = NULL;
+char *path_kmem = NULL;
+
+int verbose_flag = 0;
+int debug_flag   = 0;
+int syslog_flag  = 0;
+int multi_flag   = 0;
+int other_flag   = 0;
+int unknown_flag = 0;
+int number_flag  = 0;
+int noident_flag = 0;
+
+int lport = 0;
+int fport = 0;
+
+char *charset_name = NULL;
+char *indirect_host = NULL;
+char *indirect_password = NULL;
+
+static int child_pid;
+
+#ifdef LOG_DAEMON
+static int syslog_facility = LOG_DAEMON;
+#endif
+
+/*
+** The structure passing convention for GCC is incompatible with
+** Suns own C compiler, so we define our own inet_ntoa() function.
+** (This should only affect GCC version 1 I think, a well, this works
+** for version 2 also so why bother.. :-)
+*/
+#if defined(__GNUC__) && defined(__sparc__)
+
+#ifdef inet_ntoa
+#undef inet_ntoa
+#endif
+
+char *inet_ntoa(ad)
+  struct in_addr ad;
+{
+  unsigned long int s_ad;
+  int a, b, c, d;
+  static char addr[20];
+  
+  s_ad = ad.s_addr;
+  d = s_ad % 256;
+  s_ad /= 256;
+  c = s_ad % 256;
+  s_ad /= 256;
+  b = s_ad % 256;
+  a = s_ad / 256;
+  sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
+  
+  return addr;
+}
+#endif
+
+
+/*
+** Return the name of the connecting host, or the IP number as a string.
+*/
+char *gethost(addr)
+  struct in_addr *addr;
+{
+  struct hostent *hp;
+
+  
+  hp = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET);
+  if (hp)
+    return hp->h_name;
+  else
+    return inet_ntoa(*addr);
+}
+
+/*
+** Exit cleanly after our time's up.
+*/
+static SIGRETURN_TYPE
+alarm_handler()
+{
+  if (syslog_flag)
+    syslog(LOG_DEBUG, "SIGALRM triggered, exiting");
+  
+  exit(0);
+}
+
+#if !defined(hpux) && !defined(__hpux) && !defined(SVR4) || defined(_CRAY)
+/*
+** This is used to clean up zombie child processes
+** if the -w or -b options are used.
+*/
+static SIGRETURN_TYPE
+child_handler()
+{
+#if defined(IRIX) || defined(__APPLE__)
+  union wait status;
+#else
+  int status;
+#endif
+
+  while (wait3(&status, WNOHANG, NULL) > 0)
+    ;
+  
+#ifndef SIGRETURN_TYPE_IS_VOID
+  return 0;
+#endif
+}
+#endif
+
+
+char *clearmem(bp, len)
+  char *bp;
+  int len;
+{
+  char *cp;
+
+  cp = bp;
+  while (len-- > 0)
+    *cp++ = 0;
+
+  return bp;
+}
+
+
+/*
+** Main entry point into this daemon
+*/
+int main(argc,argv)
+  int argc;
+  char *argv[];
+{
+  int i, len;
+  struct sockaddr_in sin;
+  struct in_addr laddr, faddr;
+  struct timeval tv;
+
+  int background_flag = 0;
+  int timeout = 0;
+  char *portno = "113";
+  char *bind_address = NULL;
+  int set_uid = 0;
+  int set_gid = 0;
+  int inhibit_default_config = 0;
+  int opt_count = 0;           /* Count of option flags */
+  
+#ifdef __convex__
+  argc--;    /* get rid of extra argument passed by inetd */
+#endif
+
+  /*
+  ** Prescan the arguments for "-f<config-file>" switches
+  */
+  inhibit_default_config = 0;
+  for (i = 1; i < argc && argv[i][0] == '-'; i++)
+    if (argv[i][1] == 'f')
+      inhibit_default_config = 1;
+
+  /*
+  ** Parse the default config file - if it exists
+  */
+  if (!inhibit_default_config)
+    parse_config(NULL, 1);
+  
+  /*
+  ** Parse the command line arguments
+  */
+  for (i = 1; i < argc && argv[i][0] == '-'; i++) {
+    opt_count++;
+    switch (argv[i][1])
+    {
+      case 'b':    /* Start as standalone daemon */
+        background_flag = 1;
+       break;
+
+      case 'w':    /* Start from Inetd, wait mode */
+       background_flag = 2;
+       break;
+
+      case 'i':    /* Start from Inetd, nowait mode */
+       background_flag = 0;
+       break;
+
+      case 't':
+       timeout = atoi(argv[i]+2);
+       break;
+
+      case 'p':
+       portno = argv[i]+2;
+       break;
+
+      case 'a':
+       bind_address = argv[i]+2;
+       break;
+         
+      case 'u':
+       if (isdigit(argv[i][2]))
+         set_uid = atoi(argv[i]+2);
+       else
+       {
+         struct passwd *pwd;
+
+         pwd = getpwnam(argv[i]+2);
+         if (!pwd)
+           ERROR1("no such user (%s) for -u option", argv[i]+2);
+         else
+         {
+           set_uid = pwd->pw_uid;
+           set_gid = pwd->pw_gid;
+         }
+       }
+       break;
+       
+      case 'g':
+       if (isdigit(argv[i][2]))
+         set_gid = atoi(argv[i]+2);
+       else
+       {
+         struct group *grp;
+
+         grp = getgrnam(argv[i]+2);
+         if (!grp)
+           ERROR1("no such group (%s) for -g option", argv[i]+2);
+         else
+           set_gid = grp->gr_gid;
+       }
+       break;
+
+      case 'c':
+       charset_name = argv[i]+2;
+       break;
+
+      case 'r':
+       indirect_host = argv[i]+2;
+       break;
+
+      case 'l':    /* Use the Syslog daemon for logging */
+       syslog_flag++;
+       break;
+
+      case 'o':
+       other_flag = 1;
+       break;
+
+      case 'e':
+       unknown_flag = 1;
+       break;
+
+      case 'n':
+       number_flag = 1;
+       break;
+       
+      case 'V':    /* Give version of this daemon */
+       printf("[in.identd, version %s]\r\n", version);
+       exit(0);
+       break;
+
+      case 'v':    /* Be verbose */
+       verbose_flag++;
+       break;
+         
+      case 'd':    /* Enable debugging */
+       debug_flag++;
+       break;
+
+      case 'm':    /* Enable multiline queries */
+       multi_flag++;
+       break;
+
+      case 'N':    /* Enable users ".noident" files */
+       noident_flag++;
+       break;
+    }
+  }
+  
+#if defined(_AUX_SOURCE) || defined (SUNOS35)
+  /* A/UX 2.0* & SunOS 3.5 calls us with an argument XXXXXXXX.YYYY
+  ** where XXXXXXXXX is the hexadecimal version of the callers
+  ** IP number, and YYYY is the port/socket or something.
+  ** It seems to be impossible to pass arguments to a daemon started
+  ** by inetd.
+  **
+  ** Just in case it is started from something else, then we only
+  ** skip the argument if no option flags have been seen.
+  */
+  if (opt_count == 0)
+    argc--;
+#endif
+
+  /*
+  ** Path to kernel namelist file specified on command line
+  */
+  if (i < argc)
+    path_unix = argv[i++];
+
+  /*
+  ** Path to kernel memory device specified on command line
+  */
+  if (i < argc)
+    path_kmem = argv[i++];
+
+
+  /*
+  ** Open the kernel memory device and read the nlist table
+  */
+  if (k_open() < 0)
+      ERROR("main: k_open");
+
+  /*
+  ** Do the special handling needed for the "-b" flag
+  */
+  if (background_flag == 1)
+  {
+    struct sockaddr_in addr;
+    struct servent *sp;
+    int fd;
+
+    
+    if (fork())
+      exit(0);
+
+    close(0);
+    close(1);
+    close(2);
+
+    if (fork())
+      exit(0);
+    
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if (fd == -1)
+      ERROR("main: socket");
+    
+    if (fd != 0)
+      dup2(fd, 0);
+
+    clearmem(&addr, sizeof(addr));
+    
+    addr.sin_family = AF_INET;
+    if (bind_address == NULL)
+      addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    else
+    {
+      if (isdigit(bind_address[0]))
+       addr.sin_addr.s_addr = inet_addr(bind_address);
+      else
+      {
+       struct hostent *hp;
+
+       hp = gethostbyname(bind_address);
+       if (!hp)
+         ERROR1("no such address (%s) for -a switch", bind_address);
+
+       /* This is ugly, should use memcpy() or bcopy() but... */
+       addr.sin_addr.s_addr = * (unsigned long *) (hp->h_addr);
+      }
+    }
+
+    if (isdigit(portno[0]))
+      addr.sin_port = htons(atoi(portno));
+    else
+    {
+      sp = getservbyname(portno, "tcp");
+      if (sp == NULL)
+       ERROR1("main: getservbyname: %s", portno);
+      addr.sin_port = sp->s_port;
+    }
+    
+    if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0)
+      ERROR("main: bind");
+
+    if (listen(0, 3) < 0)
+      ERROR("main: listen");
+  }
+  
+  if (set_gid)
+    if (setgid(set_gid) == -1)
+      ERROR("main: setgid");
+  
+  if (set_uid)
+    if (setuid(set_uid) == -1)
+      ERROR("main: setuid");
+
+  /*
+  ** Do some special handling if the "-b" or "-w" flags are used
+  */
+  if (background_flag)
+  {
+    int nfds, fd;
+    fd_set read_set;
+
+
+    /*
+    ** Set up the SIGCHLD signal child termination handler so
+    ** that we can avoid zombie processes hanging around and
+    ** handle childs terminating before being able to complete the
+    ** handshake.
+    */
+#if (defined(SVR4) || defined(hpux) || defined(__hpux) || \
+     defined(_CRAY) || defined(_AUX_SOURCE))
+    signal(SIGCHLD, SIG_IGN);
+#else
+    signal(SIGCHLD, (SIGRETURN_TYPE (*)()) child_handler);
+#endif
+    
+    /*
+    ** Loop and dispatch client handling processes
+    */
+    do
+    {
+      /*
+      ** Terminate if we've been idle for 'timeout' seconds
+      */
+      if (background_flag == 2 && timeout)
+      {
+       signal(SIGALRM, alarm_handler);
+       alarm(timeout);
+      }
+      
+      /*
+      ** Wait for a connection request to occur.
+      ** Ignore EINTR (Interrupted System Call).
+      */
+      do
+      {
+       FD_ZERO(&read_set);
+       FD_SET(0, &read_set);
+
+       if (timeout)
+       {
+         tv.tv_sec = timeout;
+         tv.tv_usec = 0;
+         nfds = select(FD_SETSIZE, &read_set, NULL, NULL, &tv);
+       }
+       else
+
+       nfds = select(FD_SETSIZE, &read_set, NULL, NULL, NULL);
+      } while (nfds < 0  && errno == EINTR);
+
+      /*
+      ** An error occured in select? Just die
+      */
+      if (nfds < 0)
+       ERROR("main: select");
+
+      /*
+      ** Timeout limit reached. Exit nicely
+      */
+      if (nfds == 0)
+       exit(0);
+      
+      /*
+      ** Disable the alarm timeout
+      */
+      alarm(0);
+      
+      /*
+      ** Accept the new client
+      */
+      fd = accept(0, NULL, NULL);
+      if (fd == -1)
+       ERROR1("main: accept. errno = %d", errno);
+      
+      /*
+      ** And fork, then close the fd if we are the parent.
+      */
+      child_pid = fork();
+    } while (child_pid && (close(fd), 1));
+
+    /*
+    ** We are now in child, the parent has returned to "do" above.
+    */
+    if (dup2(fd, 0) == -1)
+      ERROR("main: dup2: failed fd 0");
+    
+    if (dup2(fd, 1) == -1)
+      ERROR("main: dup2: failed fd 1");
+    
+    if (dup2(fd, 2) == -1)
+      ERROR("main: dup2: failed fd 2");
+  }
+
+  /*
+  ** Get foreign internet address
+  */
+  len = sizeof(sin);
+  if (getpeername(0, (struct sockaddr *) &sin, &len) == -1)
+  {
+    /*
+    ** A user has tried to start us from the command line or
+    ** the network link died, in which case this message won't
+    ** reach to other end anyway, so lets give the poor user some
+    ** errors.
+    */
+    perror("in.identd: getpeername()");
+    exit(1);
+  }
+  
+  faddr = sin.sin_addr;
+
+
+  /*
+  ** Open the connection to the Syslog daemon if requested
+  */
+  if (syslog_flag)
+  {
+#ifdef LOG_DAEMON
+    openlog("identd", LOG_PID, syslog_facility);
+#else
+    openlog("identd", LOG_PID);
+#endif
+    
+    syslog(LOG_INFO, "Connection from %s", gethost(&faddr));
+  }
+  
+
+  /*
+  ** Get local internet address
+  */
+  len = sizeof(sin);
+#ifdef ATTSVR4
+  if (t_getsockname(0, (struct sockaddr *) &sin, &len) == -1)
+#else
+  if (getsockname(0, (struct sockaddr *) &sin, &len) == -1)
+#endif
+  {
+    /*
+    ** We can just die here, because if this fails then the
+    ** network has died and we haven't got anyone to return
+    ** errors to.
+    */
+    exit(1);
+  }
+  laddr = sin.sin_addr;
+
+
+  /*
+  ** Get the local/foreign port pair from the luser
+  */
+  parse(stdin, &laddr, &faddr);
+
+  exit(0);
+}
diff --git a/identd.tproj/identd.h b/identd.tproj/identd.h
new file mode 100644 (file)
index 0000000..61ece7c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: identd.h,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $
+**
+** identd.h                 Common variables for the Pidentd daemon
+**
+** This program is in the public domain and may be used freely by anyone
+** who wants to. 
+**
+** Last update: 6 Dec 1992
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#ifndef __IDENTD_H__
+#define __IDENTD_H__
+
+extern char *version;
+
+extern char *path_unix;
+extern char *path_kmem;
+
+extern int verbose_flag;
+extern int debug_flag;
+extern int syslog_flag;
+extern int multi_flag;
+extern int other_flag;
+extern int unknown_flag;
+extern int number_flag;
+extern int noident_flag;
+
+extern char *charset_name;
+extern char *indirect_host;
+extern char *indirect_password;
+
+extern int lport;
+extern int fport;
+
+extern char *gethost();
+
+extern int k_open();
+extern int k_getuid();
+extern int parse();
+extern int parse_config();
+
+#endif
diff --git a/identd.tproj/netbsd.c b/identd.tproj/netbsd.c
new file mode 100644 (file)
index 0000000..83626a4
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: netbsd.c,v 1.1.1.2 2000/01/11 01:48:48 wsanchez Exp $
+**
+** netbsd.c            Low level kernel access functions for NetBSD
+**
+** This program is in the public domain and may be used freely by anyone
+** who wants to. 
+**
+** Last update: 17 March 1993
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <nlist.h>
+#include <pwd.h>
+#include <signal.h>
+#include <syslog.h>
+
+#include "kvm.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <sys/socketvar.h>
+
+#define KERNEL
+
+#include <sys/file.h>
+
+#undef KERNEL
+#include <sys/sysctl.h>
+
+#include <fcntl.h>
+
+#include <sys/user.h>
+
+#include <sys/wait.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netinet/in_pcb.h>
+
+#include <netinet/tcp.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+
+#include <arpa/inet.h>
+
+#include "identd.h"
+#include "error.h"
+
+
+extern void *calloc();
+extern void *malloc();
+
+
+struct nlist nl[] =
+{
+#define N_FILE 0
+#define N_NFILE 1
+#define N_TCB 2
+      
+  { "_filehead" },
+  { "_nfiles" },
+  { "_tcb" },
+  { "" }
+};
+
+static kvm_t *kd;
+
+static struct file *xfile;
+static int nfile;
+
+static struct inpcbhead tcb;
+  
+
+int k_open()
+{
+  /*
+  ** Open the kernel memory device
+  */
+  if ((kd = kvm_openfiles(path_unix, path_kmem, NULL, O_RDONLY, "identd")) ==
+      NULL)
+    ERROR("main: kvm_open");
+  
+  /*
+  ** Extract offsets to the needed variables in the kernel
+  */
+  if (kvm_nlist(kd, nl) < 0)
+    ERROR("main: kvm_nlist");
+
+  return 0;
+}
+
+
+/*
+** Get a piece of kernel memory with error handling.
+** Returns 1 if call succeeded, else 0 (zero).
+*/
+static int getbuf(addr, buf, len, what)
+  long addr;
+  char *buf;
+  int len;
+  char *what;
+{
+  if (kvm_read(kd, addr, buf, len) < 0)
+  {
+    if (syslog_flag)
+      syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
+            addr, len, what);
+
+    return 0;
+  }
+  
+  return 1;
+}
+
+
+
+/*
+** Traverse the inpcb list until a match is found.
+** Returns NULL if no match.
+*/
+static struct socket *
+    getlist(pcbp_head, faddr, fport, laddr, lport)
+  struct inpcbhead *pcbp_head;
+  struct in_addr *faddr;
+  int fport;
+  struct in_addr *laddr;
+  int lport;
+{
+  struct inpcb *pcbp;
+  struct inpcb pcb;
+
+  pcbp = pcbp_head->lh_first;
+  while (pcbp &&
+          getbuf((long) pcbp,
+                 &pcb,
+                 sizeof(struct inpcb),
+                 "tcblist"))
+   {
+      if ( pcb.inp_faddr.s_addr == faddr->s_addr &&
+          pcb.inp_laddr.s_addr == laddr->s_addr &&
+          pcb.inp_fport        == fport &&
+          pcb.inp_lport        == lport )
+         return pcb.inp_socket;
+
+      pcbp = pcb.inp_list.le_next;
+  } 
+
+  return NULL;
+}
+
+
+
+/*
+** Return the user number for the connection owner
+*/
+int k_getuid(faddr, fport, laddr, lport, uid)
+  struct in_addr *faddr;
+  int fport;
+  struct in_addr *laddr;
+  int lport;
+  int *uid;
+{
+  long addr;
+  struct socket *sockp;
+  int i, mib[2];
+  struct ucred ucb;
+  
+  /* -------------------- FILE DESCRIPTOR TABLE -------------------- */
+  if (!getbuf(nl[N_NFILE].n_value, &nfile, sizeof(nfile), "nfile"))
+    return -1;
+  
+  if (!getbuf(nl[N_FILE].n_value, &addr, sizeof(addr), "&file"))
+    return -1;
+
+  {
+    int siz, rv;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_FILE;
+    if ((rv = sysctl(mib, 2, NULL, &siz, NULL, 0)) == -1)
+    {
+      ERROR1("k_getuid: sysctl 1 (%d)", rv);
+      return -1;
+    }
+    xfile = malloc(siz);
+    if (!xfile)
+      ERROR1("k_getuid: malloc(%d)", siz);
+    if ((rv = sysctl(mib, 2, xfile, &siz, NULL, 0)) == -1)
+    {
+      ERROR1("k_getuid: sysctl 2 (%d)", rv);
+      return -1;
+    }
+    xfile = (struct file *)((char *)xfile + sizeof(filehead));
+  }
+  
+  /* -------------------- TCP PCB LIST -------------------- */
+  if (!getbuf(nl[N_TCB].n_value, &tcb, sizeof(tcb), "tcb"))
+    return -1;
+  
+  sockp = getlist(&tcb, faddr, fport, laddr, lport);
+  
+  if (!sockp)
+    return -1;
+
+  /*
+  ** Locate the file descriptor that has the socket in question
+  ** open so that we can get the 'ucred' information
+  */
+  for (i = 0; i < nfile; i++)
+  {
+    if (xfile[i].f_count == 0)
+      continue;
+    
+    if (xfile[i].f_type == DTYPE_SOCKET &&
+       (struct socket *) xfile[i].f_data == sockp)
+    {
+      if (!getbuf(xfile[i].f_cred, &ucb, sizeof(ucb), "ucb"))
+       return -1;
+
+      *uid = ucb.cr_uid;
+      return 0;
+    }
+  }
+
+  return -1;
+}
+
diff --git a/identd.tproj/parse.c b/identd.tproj/parse.c
new file mode 100644 (file)
index 0000000..2d978ad
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: parse.c,v 1.2 2000/10/03 02:38:32 lindak Exp $
+**
+** parse.c                         This file contains the protocol parser
+**
+** This program is in the public domain and may be used freely by anyone
+** who wants to. 
+**
+** Last update: 6 Dec 1992
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pwd.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#ifndef HPUX7
+#  include <arpa/inet.h>
+#endif
+
+#include <nlist.h>
+#include <kvm.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(MIPS) || defined(BSD43)
+extern int errno;
+#endif
+
+#include "identd.h"
+#include "error.h"
+
+extern void *malloc();
+
+/*
+** This function will eat whitespace characters until
+** either a non-whitespace character is read, or EOF
+** occurs. This function is only used if the "-m" option
+** is enabled.
+*/
+static int eat_whitespace()
+{
+  int c;
+
+  
+  while ((c = getchar()) != EOF &&
+        !(c == '\r' || c == '\n'))
+    ;
+
+  if (c != EOF)
+    while ((c = getchar()) != EOF &&
+          (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+      ;
+
+  if (c != EOF)
+    ungetc(c, stdin);
+  
+  return (c != EOF);
+}
+
+
+#ifdef INCLUDE_EXTENSIONS
+/*
+** Validate an indirect request
+*/
+static int valid_fhost(faddr, password)
+  struct in_addr *faddr;
+  char *password;
+{
+  if (indirect_host == NULL)
+    return 0;
+
+  if (strcmp(indirect_host, "*") != 0)
+  {
+    if (isdigit(indirect_host[0]))
+    {
+      if (strcmp(inet_ntoa(*faddr), indirect_host))
+      {
+       syslog(LOG_NOTICE, "valid_fhost: access denied for: %s",
+              gethost(faddr));
+       return 0;
+      }
+    }
+    else
+    {
+      if (strcmp(gethost(faddr), indirect_host))
+      {
+       syslog(LOG_NOTICE, "valid_fhost: access denied for: %s",
+              gethost(faddr));
+       return 0;
+      }
+    }
+  }
+      
+  if (indirect_password == NULL)
+    return 1;
+  
+  if (strcmp(password, indirect_password))
+  {
+    syslog(LOG_NOTICE, "valid_fhost: invalid password from: %s",
+          gethost(faddr));
+    return 0;
+  }
+
+  return 1;
+}
+#endif
+
+/*
+** A small routine to check for the existance of the ".noident"
+** file in a users home directory.
+*/
+static int check_noident(homedir)
+  char *homedir;
+{
+  char *tmp_path;
+  struct stat sbuf;
+  int rcode;
+  
+
+  if (!homedir)
+    return 0;
+  
+  tmp_path = (char *) malloc(strlen(homedir) + sizeof("/.noident") + 1);
+  if (!tmp_path)
+    return 0;
+
+  strcpy(tmp_path, homedir);
+  strcat(tmp_path, "/.noident");
+
+  rcode = stat(tmp_path, &sbuf);
+  free(tmp_path);
+
+  return (rcode == 0);
+}
+
+
+int parse(fp, laddr, faddr)
+  FILE *fp;
+  struct in_addr *laddr, *faddr;
+{
+  int uid, try, rcode;
+  struct passwd *pwp;
+  char lhostaddr[16];
+  char fhostaddr[16];
+  char password[33];
+#ifdef INCLUDE_EXTENSIONS  
+  char arg[33];
+  int c;
+#endif
+  struct in_addr laddr2;
+  struct in_addr faddr2;
+  
+  
+  if (debug_flag && syslog_flag)
+    syslog(LOG_DEBUG, "In function parse()");
+  
+  /*
+  ** Get the local/foreign port pair from the luser
+  */
+  do
+  {
+    if (debug_flag && syslog_flag)
+      syslog(LOG_DEBUG, "  Before fscanf()");
+    
+    faddr2 = *faddr;
+    laddr2 = *laddr;
+    lport = fport = 0;
+    lhostaddr[0] = fhostaddr[0] = password[0] = '\0';
+
+    /* Read query from client */
+    rcode = fscanf(fp, " %d , %d", &lport, &fport);
+
+#ifdef INCLUDE_EXTENSIONS
+    /*
+    ** Do additional parsing in case of extended request
+    */
+    if (rcode == 0)
+    {
+      rcode = fscanf(fp, "%32[^ \t\n\r:]", arg);
+
+      /* Skip leading space up to EOF, EOL or non-space char */
+      while ((c = getc(fp)) == ' ' || c == '\t')
+       ;
+      
+      if (rcode <= 0)
+      {
+       printf("%d , %d : ERROR : %s\r\n",
+              lport, fport,
+              unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
+       continue;
+      }
+
+      /*
+      ** Non-standard extended request, returns with Pidentd
+      ** version information
+      */
+      if (strcmp(arg, "VERSION") == 0)
+      {
+       printf("%d , %d : ERROR : X-VERSION : %s\r\n", lport, fport,
+              version);
+       continue;
+      }
+
+      /*
+      ** Non-standard extended proxy request
+      */
+      else if (strcmp(arg, "PROXY") == 0 && c == ':')
+      {
+       /* We have a colon char, check for port numbers */
+       rcode = fscanf(fp, " %d , %d : %15[0-9.] , %15[0-9.]",
+                      &lport, &fport, fhostaddr, lhostaddr);
+
+       if (!(rcode == 3 || rcode == 4))
+       {
+         printf("%d , %d : ERROR : %s\r\n",
+                lport, fport,
+                unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
+         continue;
+       }
+
+       if (rcode == 4)
+         laddr2.s_addr = inet_addr(lhostaddr);
+       
+       faddr2.s_addr = inet_addr(fhostaddr);
+
+       proxy(&laddr2, &faddr2, lport, fport, NULL);
+       continue;
+      }
+      
+      /*
+      ** Non-standard extended remote indirect request
+      */
+      else if (strcmp(arg, "REMOTE") == 0 && c == ':')
+      {
+       /* We have a colon char, check for port numbers */
+       rcode = fscanf(fp, " %d , %d", &lport, &fport);
+       
+       /* Skip leading space up to EOF, EOL or non-space char */
+       while ((c = getc(fp)) == ' ' || c == '\t')
+         ;
+
+       if (rcode != 2 || c != ':')
+       {
+         printf("%d , %d : ERROR : %s\r\n",
+                lport, fport,
+                unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
+         continue;
+       }
+           
+       /* We have a colon char, check for addr and password */
+       rcode = fscanf(fp, " %15[0-9.] , %32[^ \t\r\n]",
+                      fhostaddr, password);
+       if (rcode > 0)
+         rcode += 2;
+       else
+       {
+         printf("%d , %d : ERROR : %s\r\n",
+                lport, fport,
+                unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
+         continue;
+       }
+       
+       /*
+       ** Verify that the host originating the indirect request
+       ** is allowed to do that
+       */
+       if (!valid_fhost(faddr, password))
+       {
+         printf("%d , %d : ERROR : %s\r\n",
+                lport, fport,
+                unknown_flag ? "UNKNOWN-ERROR" : "X-ACCESS-DENIED");
+         continue;
+       }
+       
+       faddr2.s_addr = inet_addr(fhostaddr);
+      }
+      
+      else
+      {
+       printf("%d , %d : ERROR : %s\r\n",
+              lport, fport,
+              unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
+       continue;
+      }
+    }
+#endif /* EXTENSIONS */
+    
+    if (rcode < 2 || lport < 1 || lport > 65535 || fport < 1 || fport > 65535)
+    {
+      if (syslog_flag && rcode > 0)
+       syslog(LOG_NOTICE, "scanf: invalid-port(s): %d , %d from %s",
+              lport, fport, gethost(faddr));
+      
+      printf("%d , %d : ERROR : %s\r\n",
+            lport, fport,
+            unknown_flag ? "UNKNOWN-ERROR" : "INVALID-PORT");
+      continue;
+    }
+
+    if (syslog_flag && verbose_flag)
+       syslog(LOG_NOTICE, "request for (%d,%d) from %s",
+              lport, fport, gethost(faddr));
+
+    if (debug_flag && syslog_flag)
+      syslog(LOG_DEBUG, "  After fscanf(), before k_getuid()");
+    
+    /*
+    ** Next - get the specific TCP connection and return the
+    ** uid - user number.
+    **
+    ** Try to fetch the information 5 times incase the
+    ** kernel changed beneath us and we missed or took
+    ** a fault.
+    */
+    for (try = 0;
+        (try < 5 &&
+          k_getuid(&faddr2, htons(fport), laddr, htons(lport), &uid) == -1);
+        try++)
+      ;
+
+    if (try >= 5)
+    {
+      if (syslog_flag)
+       syslog(LOG_DEBUG, "Returned: %d , %d : NO-USER", lport, fport);
+      
+      printf("%d , %d : ERROR : %s\r\n",
+            lport, fport,
+            unknown_flag ? "UNKNOWN-ERROR" : "NO-USER");
+      continue;
+    }
+
+    if (try > 0 && syslog_flag)
+      syslog(LOG_NOTICE, "k_getuid retries: %d", try);
+    
+    if (debug_flag && syslog_flag)
+      syslog(LOG_DEBUG, "  After k_getuid(), before getpwuid()");
+
+    /*
+    ** Then we should try to get the username. If that fails we
+    ** return it as an OTHER identifier
+    */
+    pwp = getpwuid(uid);
+    
+    if (!pwp)
+    {
+      if (syslog_flag)
+       syslog(LOG_WARNING, "getpwuid() could not map uid (%d) to name",
+              uid);
+
+      printf("%d , %d : USERID : OTHER%s%s : %d\r\n",
+            lport, fport,
+            charset_name ? " , " : "",
+            charset_name ? charset_name : "",
+            uid);
+      continue;
+    }
+
+    /*
+    ** Hey! We finally made it!!!
+    */
+    if (syslog_flag)
+      syslog(LOG_DEBUG, "Successful lookup: %d , %d : %s",
+            lport, fport, pwp->pw_name);
+
+    if (noident_flag && check_noident(pwp->pw_dir))
+    {
+      if (syslog_flag && verbose_flag)
+       syslog(LOG_NOTICE, "user %s requested HIDDEN-USER for host %s: %d, %d",
+              pwp->pw_name,
+              gethost(faddr),
+              lport, fport);
+      
+      printf("%d , %d : ERROR : HIDDEN-USER\r\n",
+          lport, fport);
+      continue;
+    }
+
+    if (number_flag)
+      printf("%d , %d : USERID : OTHER%s%s : %d\r\n",
+            lport, fport,
+            charset_name ? " , " : "",
+            charset_name ? charset_name : "",
+            uid);
+    else
+      printf("%d , %d : USERID : %s%s%s : %s\r\n",
+            lport, fport,
+            other_flag ? "OTHER" : "UNIX",
+            charset_name ? " , " : "",
+            charset_name ? charset_name : "",
+            pwp->pw_name);
+    
+  } while(fflush(stdout), fflush(stderr), multi_flag && eat_whitespace());
+
+  return 0;
+}
diff --git a/identd.tproj/proxy.c b/identd.tproj/proxy.c
new file mode 100644 (file)
index 0000000..a64c581
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: proxy.c,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $
+**
+** proxy.c                         This file implements the proxy() call.
+**
+** This program is in the public domain and may be used freely by anyone
+** who wants to. 
+**
+** Last update: 12 Dec 1992
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "identd.h"
+
+
+#ifdef INCLUDE_PROXY
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include <ident.h>
+#endif
+
+
+/*
+** This function should establish a connection to a remote IDENT
+** server and query it for the information associated with the
+** specified connection and the return that to the caller.
+**
+** Should there be three different timeouts (Connection Establishment,
+** Query Transmit and Query Receive)?
+*/
+int proxy(laddr, faddr, lport, fport, timeout)
+  struct in_addr *laddr;
+  struct in_addr *faddr;
+  int lport;
+  int fport;
+  struct timeval *timeout;
+{
+#ifndef INCLUDE_PROXY
+  printf("%d , %d : ERROR : %s\r\n",
+        lport, fport,
+        unknown_flag ? "UNKNOWN-ERROR" : "X-NOT-YET-IMPLEMENTED");
+  
+  return -1;
+#else
+  id_t *idp;
+  char *answer;
+  char *opsys;
+  char *charset;
+  
+  idp = id_open(laddr, faddr, timeout);
+  if (!idp)
+  {
+    printf("%d , %d : ERROR : %s\r\n",
+          lport, fport,
+          unknown_flag ? "UNKNOWN-ERROR" : "X-CONNECTION-REFUSED");
+    return -1;
+  }
+
+  if (id_query(idp, lport, fport, timeout) < 0)
+  {
+    printf("%d , %d : ERROR : %s\r\n",
+          lport, fport,
+          unknown_flag ? "UNKNOWN-ERROR" : "X-TRANSMIT-QUERY-ERROR");
+    id_close(idp);
+    return -1;
+  }
+
+  switch (id_parse(idp, timeout, &lport, &fport, &answer, &opsys, &charset))
+  {
+    case 1:
+      printf("%d , %d : USERID : %s %s%s : %s\r\n",
+            lport, fport,
+            opsys,
+            charset ? "," : "",
+            charset ? charset : "",
+            answer);
+      break;
+      
+    case 2:
+      printf("%d , %d : ERROR : %s\r\n",
+            lport, fport, answer);
+      break;
+      
+    case 0:  /* More to parse - fix this later! */
+    case -1: /* Internal error */
+    default:
+      printf("%d , %d : ERROR : %s\r\n",
+            lport, fport,
+            unknown_flag ? "UNKNOWN-ERROR" : "X-PARSE-REPLY-ERROR");
+  }
+
+  id_close(idp);
+#endif  
+}
diff --git a/identd.tproj/version.c b/identd.tproj/version.c
new file mode 100644 (file)
index 0000000..dbeeab2
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $Id: version.c,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $ */
+char *version = "2.1.2";
diff --git a/identd.tproj/xpaths.h b/identd.tproj/xpaths.h
new file mode 100644 (file)
index 0000000..df55f1a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+**     $Id: xpaths.h,v 1.1.1.2 2000/01/11 01:48:48 wsanchez Exp $
+**
+** paths.h             Common path definitions for the in.identd daemon
+**
+** Last update: 11 Dec 1992
+**
+** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
+*/
+
+#include <paths.h>
+
+#ifdef SEQUENT
+#  define _PATH_UNIX "/dynix"
+#endif
+
+#if defined(MIPS) || defined(IRIX)
+#  define _PATH_UNIX "/unix"
+#endif
+
+#if defined(hpux) || defined(__hpux)
+#  define _PATH_UNIX "/hp-ux"
+#endif
+
+#ifdef SOLARIS
+#  define _PATH_UNIX "/dev/ksyms"
+#else
+#  ifdef SVR4
+#    define _PATH_UNIX "/stand/unix"
+#  endif
+#endif
+
+#ifdef BSD43
+#  define _PATH_SWAP "/dev/drum"
+#  define _PATH_MEM  "/dev/mem"
+#endif
+
+#ifdef _AUX_SOURCE
+#  define _PATH_UNIX "/unix"
+#endif
+
+#ifdef _CRAY
+#  define _PATH_UNIX "/unicos"
+#  define _PATH_MEM  "/dev/mem"
+#endif
+
+#ifdef __APPLE__
+#  define _PATH_UNIX "/mach"
+#endif
+
+
+/*
+ * Some defaults...
+ */
+#ifndef _PATH_KMEM
+#  define _PATH_KMEM "/dev/kmem"
+#endif
+
+#ifndef _PATH_UNIX
+#  define _PATH_UNIX "/vmunix"
+#endif
+
+
+#ifndef PATH_CONFIG
+#  define PATH_CONFIG "/etc/identd.conf"
+#endif
diff --git a/ifconfig.tproj/Makefile b/ifconfig.tproj/Makefile
new file mode 100644 (file)
index 0000000..2ae172d
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the Apple Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ifconfig
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = ifconfig.h
+
+CFILES = ifconfig.c ifmedia.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist ifconfig.8\
+            Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ifconfig.tproj/Makefile.dist b/ifconfig.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..8be2193
--- /dev/null
@@ -0,0 +1,6 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  ifconfig
+MAN8=  ifconfig.0
+
+.include <bsd.prog.mk>
diff --git a/ifconfig.tproj/Makefile.postamble b/ifconfig.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..c188e2f
--- /dev/null
@@ -0,0 +1,3 @@
+after_install:
+       install -d $(DSTROOT)/usr/share/man/man8
+       install -c -m 444 ifconfig.8 $(DSTROOT)/usr/share/man/man8
diff --git a/ifconfig.tproj/Makefile.preamble b/ifconfig.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..5a6d897
--- /dev/null
@@ -0,0 +1,3 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
+OTHER_CFLAGS += -DUSE_IF_MEDIA
diff --git a/ifconfig.tproj/PB.project b/ifconfig.tproj/PB.project
new file mode 100644 (file)
index 0000000..e699c93
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (ifconfig.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (ifconfig.c, ifmedia.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, ifconfig.8, Makefile.postamble); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = ifconfig; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = ifconfig; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ifconfig; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = ifconfig; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ifconfig.tproj/ifconfig.8 b/ifconfig.tproj/ifconfig.8
new file mode 100644 (file)
index 0000000..216d66a
--- /dev/null
@@ -0,0 +1,320 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)ifconfig.8 8.4 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt IFCONFIG 8
+.Os BSD 4.2
+.Sh NAME
+.Nm ifconfig
+.Nd configure network interface parameters
+.Sh SYNOPSIS
+.Nm ifconfig
+.Ar interface address_family
+.Oo
+.Ar address
+.Op Ar dest_address
+.Oc
+.Op Ar parameters
+.Nm ifconfig
+.Ar interface
+.Op Ar protocol_family
+.Nm ifconfig
+.Fl a
+.Op Fl d
+.Op Fl u
+.Op Ar address_family
+.Nm ifconfig
+.Fl l
+.Op Fl d
+.Op Fl u
+.Op Ar address_family
+.Sh DESCRIPTION
+.Nm Ifconfig
+is used to assign an address
+to a network interface and/or configure
+network interface parameters.
+.Nm Ifconfig
+must be used at boot time to define the network address
+of each interface present on a machine; it may also be used at
+a later time to redefine an interface's address
+or other operating parameters.
+.Pp
+Available operands for
+.Nm ifconfig:
+.Bl -tag -width Ds
+.It Ar Address
+For the
+.Tn DARPA-Internet
+family,
+the address is either a host name present in the host name data
+base, 
+.Xr hosts 5 ,
+or a
+.Tn DARPA
+Internet address expressed in the Internet standard
+.Dq dot notation .
+For the Xerox Network Systems(tm) family,
+addresses are 
+.Ar net:a.b.c.d.e.f ,
+where
+.Ar net
+is the assigned network number (in decimal),
+and each of the six bytes of the host number,
+.Ar a
+through
+.Ar f ,
+are specified in hexadecimal.
+The host number may be omitted on 10Mb/s Ethernet interfaces,
+which use the hardware physical address,
+and on interfaces other than the first.
+For the
+.Tn ISO
+family, addresses are specified as a long hexadecimal string,
+as in the Xerox family.  However, two consecutive dots imply a zero
+byte, and the dots are optional, if the user wishes to (carefully)
+count out long strings of digits in network byte order.
+.It Ar address_family
+Specifies the
+.Ar address family
+which affects interpretation of the remaining parameters.
+Since an interface can receive transmissions in differing protocols
+with different naming schemes, specifying the address family is recommeded.
+The address or protocol families currently
+supported are
+.Dq inet ,
+.Dq iso ,
+and
+.Dq ns .
+.It Ar Interface
+The
+.Ar interface
+parameter is a string of the form
+.Dq name unit ,
+for example,
+.Dq en0 
+.El
+.Pp
+The following parameters may be set with 
+.Nm ifconfig :
+.Bl -tag -width dest_addressxx
+.It Cm alias
+Establish an additional network address for this interface.  This is
+sometimes useful when changing network numbers, and one wishes to
+accept packets addressed to the old interface. 
+A
+.Ar netmask
+should be used with this parameter.
+If the new (
+.Ar alias
+) address is on the same subnet as an existing address assigned to
+this interface, the netmask must be "255.255.255.255".  If a netmask
+is not supplied, the command will use the one implied by the address
+itself (e.g, Class A).  If the 'all ones' netmask is used, the system
+will handle route installation.  If another netmask is used, a route
+to that address must be installed by hand, e.g., "route add -host
+XX.XX.XX.XX -interface 127.0.0.1", where "XX.XX.XX.XX" is the new
+alias (c.f.
+.Ar route
+(8)).  In either case, the administrator may have to remove a route
+by hand when the alias is removed (
+.Ar -alias
+or 
+.Ar delete
+)
+.It Cm arp
+Enable the use of the Address Resolution Protocol in mapping
+between network level addresses and link level addresses (default).
+This is currently implemented for mapping between
+.Tn DARPA
+Internet
+addresses and 10Mb/s Ethernet addresses.
+.It Fl arp
+Disable the use of the Address Resolution Protocol.
+.It Cm broadcast
+(Inet only)
+Specify the address to use to represent broadcasts to the
+network.
+The default broadcast address is the address with a host part of all 1's.
+.It Cm debug
+Enable driver dependent debugging code; usually, this turns on
+extra console error logging.
+.It Fl debug
+Disable driver dependent debugging code.
+.ne 1i
+.It Cm delete
+Remove the network address specified.
+This would be used if you incorrectly specified an alias, or it
+was no longer needed.
+If you have incorrectly set an NS address having the side effect
+of specifying the host portion, removing all NS addresses will
+allow you to respecify the host portion.
+.It Cm dest_address
+Specify the address of the correspondent on the other end
+of a point to point link.
+.It Cm down
+Mark an interface ``down''.  When an interface is
+marked ``down'', the system will not attempt to
+transmit messages through that interface. 
+If possible, the interface will be reset to disable reception as well.
+This action does not automatically disable routes using the interface.
+.It Cm ipdst
+This is used to specify an Internet host who is willing to receive
+ip packets encapsulating NS packets bound for a remote network.
+An apparent point to point link is constructed, and
+the address specified will be taken as the NS address and network
+of the destination.
+IP encapsulation of
+.Tn CLNP
+packets is done differently.
+.It Cm metric Ar n
+Set the routing metric of the interface to
+.Ar n ,
+default 0.
+The routing metric is used by the routing protocol
+.Pq Xr routed 8 .
+Higher metrics have the effect of making a route
+less favorable; metrics are counted as addition hops
+to the destination network or host.
+.It Cm netmask Ar mask
+(Inet and ISO)
+Specify how much of the address to reserve for subdividing
+networks into sub-networks.
+The mask includes the network part of the local address
+and the subnet part, which is taken from the host field of the address.
+The mask can be specified as a single hexadecimal number
+with a leading 0x, with a dot-notation Internet address,
+or with a pseudo-network name listed in the network table
+.Xr networks 5 .
+The mask contains 1's for the bit positions in the 32-bit address
+which are to be used for the network and subnet parts,
+and 0's for the host part.
+The mask should contain at least the standard network portion,
+and the subnet field should be contiguous with the network
+portion.
+.\" see 
+.\" Xr eon 5 .
+.It Cm nsellength Ar n
+.Pf ( Tn ISO
+only)
+This specifies a trailing number of bytes for a received
+.Tn NSAP
+used for local identification, the remaining leading part of which is
+taken to be the
+.Tn NET
+(Network Entity Title).
+The default value is 1, which is conformant to US
+.Tn GOSIP .
+When an ISO address is set in an ifconfig command,
+it is really the
+.Tn NSAP
+which is being specified.
+For example, in
+.Tn US GOSIP ,
+20 hex digits should be
+specified in the
+.Tn ISO NSAP
+to be assigned to the interface.
+There is some evidence that a number different from 1 may be useful
+for
+.Tn AFI
+37 type addresses.
+.It Cm trailers
+Request the use of a ``trailer'' link level encapsulation when
+sending (default).
+If a network interface supports
+.Cm trailers ,
+the system will, when possible, encapsulate outgoing
+messages in a manner which minimizes the number of
+memory to memory copy operations performed by the receiver.
+On networks that support the Address Resolution Protocol (see
+.Xr arp 4 ;
+currently, only 10 Mb/s Ethernet),
+this flag indicates that the system should request that other
+systems use trailers when sending to this host.
+Similarly, trailer encapsulations will be sent to other
+hosts that have made such requests.
+Currently used by Internet protocols only.
+.It Fl trailers
+Disable the use of a ``trailer'' link level encapsulation.
+.It Cm link[0-2]
+Enable special processing of the link level of the interface.
+These three options are interface specific in actual effect, however,
+they are in general used to select special modes of operation. An example
+of this is to enable SLIP compression. Currently, only used by SLIP.
+.ne 1i
+.It Fl link[0-2]
+Disable special processing at the link level with the specified interface.
+.It Cm up
+Mark an interface ``up''. 
+This may be used to enable an interface after an ``ifconfig down.''
+It happens automatically when setting the first address on an interface.
+If the interface was reset when previously marked down,
+the hardware will be re-initialized.
+.El
+.Pp
+Special flags for 
+.Nm ifconfig:
+.Bl -tag -width Ds
+.It -a
+Produce a full listing for all available interfaces.
+.It -l
+Produce a name-only listing for all available interfaces.
+.It -d
+limit the listing to those interfaces that are down.
+.It -u
+limit the listing to those interfaces that are up.
+.El
+.Pp
+.Pp
+.Nm Ifconfig
+displays the current configuration for a network interface
+when no optional parameters are supplied.
+If a protocol family is specified,
+Ifconfig will report only the details specific to that protocol family.
+.Pp
+Only the super-user may modify the configuration of a network interface.
+.Sh DIAGNOSTICS
+Messages indicating the specified interface does not exit, the
+requested address is unknown, or the user is not privileged and
+tried to alter an interface's configuration.
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr netintro 4 ,
+.Xr rc 8 ,
+.Xr routed 8 ,
+.\" .Xr eon 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/ifconfig.tproj/ifconfig.c b/ifconfig.tproj/ifconfig.c
new file mode 100644 (file)
index 0000000..0165a69
--- /dev/null
@@ -0,0 +1,870 @@
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
+#endif
+static const char rcsid[] =
+       "$Id: ifconfig.c,v 1.1.1.2 2000/01/11 01:48:49 wsanchez Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+/* IP */
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+/* OSI */
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+struct ifreq           ifr, ridreq;
+struct ifaliasreq      addreq;
+struct sockaddr_in     netmask;
+
+
+char   name[32];
+int    flags;
+int    metric;
+int    mtu;
+int    setaddr;
+int    setipdst;
+int    doalias;
+int    clearaddr;
+int    newaddr = 1;
+
+struct afswtch;
+
+void   Perror __P((const char *cmd));
+
+int    ifconfig __P((int argc, char *const *argv, const struct afswtch *afp));
+void   notealias __P((const char *, int, int, const struct afswtch *afp));
+void   printb __P((const char *s, unsigned value, const char *bits));
+void   rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
+void   status __P((const struct afswtch *afp, int addrcount,
+                   struct sockaddr_dl *sdl, struct if_msghdr *ifm,
+                   struct ifa_msghdr *ifam));
+void   usage __P((void));
+
+typedef        void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp));
+
+c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask;
+c_func setifipdst;
+c_func setifflags, setifmetric, setifmtu;
+
+
+#define        NEXTARG         0xffffff
+
+const
+struct cmd {
+       const   char *c_name;
+       int     c_parameter;            /* NEXTARG means next argv */
+       void    (*c_func) __P((const char *, int, int, const struct afswtch *afp));
+} cmds[] = {
+       { "up",         IFF_UP,         setifflags } ,
+       { "down",       -IFF_UP,        setifflags },
+       { "arp",        -IFF_NOARP,     setifflags },
+       { "-arp",       IFF_NOARP,      setifflags },
+       { "debug",      IFF_DEBUG,      setifflags },
+       { "-debug",     -IFF_DEBUG,     setifflags },
+       { "alias",      IFF_UP,         notealias },
+       { "-alias",     -IFF_UP,        notealias },
+       { "delete",     -IFF_UP,        notealias },
+#ifdef notdef
+#define        EN_SWABIPS      0x1000
+       { "swabips",    EN_SWABIPS,     setifflags },
+       { "-swabips",   -EN_SWABIPS,    setifflags },
+#endif
+       { "netmask",    NEXTARG,        setifnetmask },
+       { "range",      NEXTARG,        0 },
+       { "phase",      NEXTARG,        0 },
+       { "metric",     NEXTARG,        setifmetric },
+       { "broadcast",  NEXTARG,        setifbroadaddr },
+       { "ipdst",      NEXTARG,        setifipdst },
+       { "link0",      IFF_LINK0,      setifflags },
+       { "-link0",     -IFF_LINK0,     setifflags },
+       { "link1",      IFF_LINK1,      setifflags },
+       { "-link1",     -IFF_LINK1,     setifflags },
+       { "link2",      IFF_LINK2,      setifflags },
+       { "-link2",     -IFF_LINK2,     setifflags },
+#if USE_IF_MEDIA
+       { "media",      NEXTARG,        setmedia },
+       { "mediaopt",   NEXTARG,        setmediaopt },
+       { "-mediaopt",  NEXTARG,        unsetmediaopt },
+#endif
+       { "normal",     -IFF_LINK0,     setifflags },
+       { "compress",   IFF_LINK0,      setifflags },
+       { "noicmp",     IFF_LINK1,      setifflags },
+       { "mtu",        NEXTARG,        setifmtu },
+       { 0,            0,              setifaddr },
+       { 0,            0,              setifdstaddr },
+};
+
+/*
+ * XNS support liberally adapted from code written at the University of
+ * Maryland principally by James O'Toole and Chris Torek.
+ */
+typedef        void af_status __P((int, struct rt_addrinfo *));
+typedef        void af_getaddr __P((const char *, int));
+
+af_status      in_status, ipx_status, at_status, ether_status;
+af_getaddr     in_getaddr, ipx_getaddr, at_getaddr;
+
+/* Known address families */
+const
+struct afswtch {
+       const char *af_name;
+       short af_af;
+       af_status *af_status;
+       af_getaddr *af_getaddr;
+       u_long af_difaddr;
+       u_long af_aifaddr;
+       caddr_t af_ridreq;
+       caddr_t af_addreq;
+} afs[] = {
+#define C(x) ((caddr_t) &x)
+       { "inet", AF_INET, in_status, in_getaddr,
+            SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
+       { "ether", AF_INET, ether_status, NULL },       /* XXX not real!! */
+#if 0  /* XXX conflicts with the media command */
+#if USE_IF_MEDIA
+       { "media", AF_INET, media_status, NULL },       /* XXX not real!! */
+#endif
+#endif
+       { 0,    0,          0,          0 }
+};
+
+/*
+ * Expand the compacted form of addresses as returned via the
+ * configuration read via sysctl().
+ */
+
+#define ROUNDUP(a) \
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+void
+rt_xaddrs(cp, cplim, rtinfo)
+       caddr_t cp, cplim;
+       struct rt_addrinfo *rtinfo;
+{
+       struct sockaddr *sa;
+       int i;
+
+       memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
+       for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+               if ((rtinfo->rti_addrs & (1 << i)) == 0)
+                       continue;
+               rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+               ADVANCE(cp, sa);
+       }
+}
+
+
+void
+usage()
+{
+       fprintf(stderr, "%s\n%s\n%s\n%s\n",
+       "usage: ifconfig interface address_family [address [dest_address]]",
+       "                [parameters]",
+       "       ifconfig -a [-d] [-u] [address_family]",
+       "       ifconfig -l [-d] [-u] [address_family]");
+       exit(1);
+}
+
+int
+main(argc, argv)
+       int argc;
+       char *const *argv;
+{
+       int c;
+       int all, namesonly, downonly, uponly;
+       int foundit = 0, need_nl = 0;
+       const struct afswtch *afp = 0;
+       int addrcount;
+       struct  if_msghdr *ifm, *nextifm;
+       struct  ifa_msghdr *ifam;
+       struct  sockaddr_dl *sdl;
+       char    *buf, *lim, *next;
+
+
+       size_t needed;
+       int mib[6];
+
+       /* Parse leading line options */
+       all = downonly = uponly = namesonly = 0;
+       while ((c = getopt(argc, argv, "adlmu")) != -1) {
+               switch (c) {
+               case 'a':       /* scan all interfaces */
+                       all++;
+                       break;
+               case 'l':       /* scan interface names only */
+                       namesonly++;
+                       break;
+               case 'd':       /* restrict scan to "down" interfaces */
+                       downonly++;
+                       break;
+               case 'u':       /* restrict scan to "up" interfaces */
+                       uponly++;
+                       break;
+               case 'm':       /* show media choices in status */
+                       /* ignored for compatibility */
+                       break;
+               default:
+                       usage();
+                       break;
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       /* -l cannot be used with -a or -m */
+       if (namesonly && all)
+               usage();
+
+       /* nonsense.. */
+       if (uponly && downonly)
+               usage();
+
+       /* -a and -l allow an address family arg to limit the output */
+       if (all || namesonly) {
+               if (argc > 1)
+                       usage();
+
+               if (argc == 1) {
+                       for (afp = afs; afp->af_name; afp++)
+                               if (strcmp(afp->af_name, *argv) == 0) {
+                                       argc--, argv++;
+                                       break;
+                               }
+                       if (afp->af_name == NULL)
+                               usage();
+                       /* leave with afp non-zero */
+               }
+       } else {
+               /* not listing, need an argument */
+               if (argc < 1)
+                       usage();
+
+               strncpy(name, *argv, sizeof(name));
+               argc--, argv++;
+       }
+
+       /* Check for address family */
+       if (argc > 0) {
+               for (afp = afs; afp->af_name; afp++)
+                       if (strcmp(afp->af_name, *argv) == 0) {
+                               argc--, argv++;
+                               break;
+                       }
+               if (afp->af_name == NULL)
+                       afp = NULL;     /* not a family, NULL */
+       }
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;
+       mib[3] = 0;     /* address family */
+       mib[4] = NET_RT_IFLIST;
+       mib[5] = 0;
+
+       /* if particular family specified, only ask about it */
+       if (afp)
+               mib[3] = afp->af_af;
+
+       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+               errx(1, "iflist-sysctl-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               errx(1, "malloc");
+       if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+               errx(1, "actual retrieval of interface table");
+       lim = buf + needed;
+
+       next = buf;
+       while (next < lim) {
+
+               ifm = (struct if_msghdr *)next;
+               
+               if (ifm->ifm_type == RTM_IFINFO) {
+                       sdl = (struct sockaddr_dl *)(ifm + 1);
+                       flags = ifm->ifm_flags;
+               } else {
+                       fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n");
+                       fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO,
+                               ifm->ifm_type);
+                       fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
+                       fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next,
+                               lim);
+                       exit (1);
+               }
+
+               next += ifm->ifm_msglen;
+               ifam = NULL;
+               addrcount = 0;
+               while (next < lim) {
+
+                       nextifm = (struct if_msghdr *)next;
+
+                       if (nextifm->ifm_type != RTM_NEWADDR)
+                               break;
+
+                       if (ifam == NULL)
+                               ifam = (struct ifa_msghdr *)nextifm;
+
+                       addrcount++;
+                       next += nextifm->ifm_msglen;
+               }
+
+               if (all || namesonly) {
+                       if (uponly)
+                               if ((flags & IFF_UP) == 0)
+                                       continue; /* not up */
+                       if (downonly)
+                               if (flags & IFF_UP)
+                                       continue; /* not down */
+                       strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
+                       name[sdl->sdl_nlen] = '\0';
+                       if (namesonly) {
+                               if (afp == NULL ||
+                                       afp->af_status != ether_status ||
+                                       sdl->sdl_type == IFT_ETHER) {
+                                       if (need_nl)
+                                               putchar(' ');
+                                       fputs(name, stdout);
+                                       need_nl++;
+                               }
+                               continue;
+                       }
+               } else {
+                       if (strlen(name) != sdl->sdl_nlen)
+                               continue; /* not same len */
+                       if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
+                               continue; /* not same name */
+               }
+
+               if (argc > 0)
+                       ifconfig(argc, argv, afp);
+               else
+                       status(afp, addrcount, sdl, ifm, ifam);
+
+               if (all == 0 && namesonly == 0) {
+                       foundit++; /* flag it as 'done' */
+                       break;
+               }
+       }
+       free(buf);
+
+       if (namesonly && need_nl > 0)
+               putchar('\n');
+
+       if (all == 0 && namesonly == 0 && foundit == 0)
+               errx(1, "interface %s does not exist", name);
+
+
+       exit (0);
+}
+
+
+int
+ifconfig(argc, argv, afp)
+       int argc;
+       char *const *argv;
+       const struct afswtch *afp;
+{
+       int s;
+
+       if (afp == NULL)
+               afp = &afs[0];
+       ifr.ifr_addr.sa_family = afp->af_af;
+       strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
+
+       if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
+               err(1, "socket");
+
+       while (argc > 0) {
+               register const struct cmd *p;
+
+               for (p = cmds; p->c_name; p++)
+                       if (strcmp(*argv, p->c_name) == 0)
+                               break;
+               if (p->c_name == 0 && setaddr)
+                       p++;    /* got src, do dst */
+               if (p->c_func) {
+                       if (p->c_parameter == NEXTARG) {
+                               if (argv[1] == NULL)
+                                       errx(1, "'%s' requires argument",
+                                           p->c_name);
+                               (*p->c_func)(argv[1], 0, s, afp);
+                               argc--, argv++;
+                       } else
+                               (*p->c_func)(*argv, p->c_parameter, s, afp);
+               }
+               argc--, argv++;
+       }
+
+       if (clearaddr) {
+               if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
+                       warnx("interface %s cannot change %s addresses!",
+                             name, afp->af_name);
+                       clearaddr = NULL;
+               }
+       }
+       if (clearaddr) {
+               int ret;
+               strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
+               if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) {
+                       if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
+                               /* means no previous address for interface */
+                       } else
+                               Perror("ioctl (SIOCDIFADDR)");
+               }
+       }
+       if (newaddr) {
+               if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
+                       warnx("interface %s cannot change %s addresses!",
+                             name, afp->af_name);
+                       newaddr = NULL;
+               }
+       }
+       if (newaddr) {
+               strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
+               if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
+                       Perror("ioctl (SIOCAIFADDR)");
+       }
+       close(s);
+       return(0);
+}
+#define RIDADDR 0
+#define ADDR   1
+#define MASK   2
+#define DSTADDR        3
+
+/*ARGSUSED*/
+void
+setifaddr(addr, param, s, afp)
+       const char *addr;
+       int param;
+       int s;
+       const struct afswtch *afp;
+{
+       /*
+        * Delay the ioctl to set the interface addr until flags are all set.
+        * The address interpretation may depend on the flags,
+        * and the flags may change when the address is set.
+        */
+       setaddr++;
+       if (doalias == 0)
+               clearaddr = 1;
+       (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
+}
+
+void
+setifnetmask(addr, dummy, s, afp)
+       const char *addr;
+       int dummy ;
+       int s;
+       const struct afswtch *afp;
+{
+       (*afp->af_getaddr)(addr, MASK);
+}
+
+void
+setifbroadaddr(addr, dummy, s, afp)
+       const char *addr;
+       int dummy ;
+       int s;
+       const struct afswtch *afp;
+{
+       (*afp->af_getaddr)(addr, DSTADDR);
+}
+
+void
+setifipdst(addr, dummy, s, afp)
+       const char *addr;
+       int dummy ;
+       int s;
+       const struct afswtch *afp;
+{
+       in_getaddr(addr, DSTADDR);
+       setipdst++;
+       clearaddr = 0;
+       newaddr = 0;
+}
+#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
+
+void
+notealias(addr, param, s, afp)
+       const char *addr;
+       int param;
+       int s;
+       const struct afswtch *afp;
+{
+       if (setaddr && doalias == 0 && param < 0)
+               bcopy((caddr_t)rqtosa(af_addreq),
+                     (caddr_t)rqtosa(af_ridreq),
+                     rqtosa(af_addreq)->sa_len);
+       doalias = param;
+       if (param < 0) {
+               clearaddr = 1;
+               newaddr = 0;
+       } else
+               clearaddr = 0;
+}
+
+/*ARGSUSED*/
+void
+setifdstaddr(addr, param, s, afp)
+       const char *addr;
+       int param ;
+       int s;
+       const struct afswtch *afp;
+{
+       (*afp->af_getaddr)(addr, DSTADDR);
+}
+
+void
+setifflags(vname, value, s, afp)
+       const char *vname;
+       int value;
+       int s;
+       const struct afswtch *afp;
+{
+       if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
+               Perror("ioctl (SIOCGIFFLAGS)");
+               exit(1);
+       }
+       strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+       flags = ifr.ifr_flags;
+
+       if (value < 0) {
+               value = -value;
+               flags &= ~value;
+       } else
+               flags |= value;
+       ifr.ifr_flags = flags;
+       if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
+               Perror(vname);
+}
+
+void
+setifmetric(val, dummy, s, afp)
+       const char *val;
+       int dummy ;
+       int s;
+       const struct afswtch *afp;
+{
+       strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+       ifr.ifr_metric = atoi(val);
+       if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
+               warn("ioctl (set metric)");
+}
+
+void
+setifmtu(val, dummy, s, afp)
+       const char *val;
+       int dummy ;
+       int s;
+       const struct afswtch *afp;
+{
+       strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+       ifr.ifr_mtu = atoi(val);
+       if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
+               warn("ioctl (set mtu)");
+}
+
+
+#define        IFFBITS \
+"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6b6\7RUNNING" \
+"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
+"\20MULTICAST"
+
+/*
+ * Print the status of the interface.  If an address family was
+ * specified, show it and it only; otherwise, show them all.
+ */
+void
+status(afp, addrcount, sdl, ifm, ifam)
+       const struct afswtch *afp;
+       int addrcount;
+       struct  sockaddr_dl *sdl;
+       struct if_msghdr *ifm;
+       struct ifa_msghdr *ifam;
+{
+       const struct afswtch *p = NULL;
+       struct  rt_addrinfo info;
+       int allfamilies, s;
+
+       if (afp == NULL) {
+               allfamilies = 1;
+               afp = &afs[0];
+       } else
+               allfamilies = 0;
+
+       ifr.ifr_addr.sa_family = afp->af_af;
+       strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
+
+       if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
+               err(1, "socket");
+
+       /*
+        * XXX is it we are doing a SIOCGIFMETRIC etc for one family.
+        * is it possible that the metric and mtu can be different for
+        * each family?  If so, we have a format problem, because the
+        * metric and mtu is printed on the global the flags line.
+        */
+       if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
+               warn("ioctl (SIOCGIFMETRIC)");
+       else
+               metric = ifr.ifr_metric;
+
+       if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
+               warn("ioctl (SIOCGIFMTU)");
+       else
+               mtu = ifr.ifr_mtu;
+
+       printf("%s: ", name);
+       printb("flags", flags, IFFBITS);
+       if (metric)
+               printf(" metric %d", metric);
+       if (mtu)
+               printf(" mtu %d", mtu);
+       putchar('\n');
+
+       while (addrcount > 0) {
+               
+               info.rti_addrs = ifam->ifam_addrs;
+
+               /* Expand the compacted addresses */
+               rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
+                         &info);
+
+               if (!allfamilies) {
+                       if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family &&
+#if USE_IF_MEDIA
+                           afp->af_status != media_status &&
+#endif
+                           afp->af_status != ether_status) {
+                               p = afp;
+                               (*p->af_status)(s, &info);
+                       }
+               } else for (p = afs; p->af_name; p++) {
+                       if (p->af_af == info.rti_info[RTAX_IFA]->sa_family &&
+#if USE_IF_MEDIA
+                           p->af_status != media_status &&
+#endif
+                           p->af_status != ether_status) 
+                               (*p->af_status)(s, &info);
+               }
+               addrcount--;
+               ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
+       }
+       if (allfamilies || afp->af_status == ether_status)
+               ether_status(s, (struct rt_addrinfo *)sdl);
+#if USE_IF_MEDIA
+       if (allfamilies || afp->af_status == media_status)
+               media_status(s, NULL);
+#endif
+       if (!allfamilies && !p && 
+           afp->af_status != ether_status)
+               warnx("%s has no %s interface address!", name, afp->af_name);
+
+       close(s);
+       return;
+}
+
+void
+in_status(s, info)
+       int s ;
+       struct rt_addrinfo * info;
+{
+       struct sockaddr_in *sin, null_sin;
+       
+       memset(&null_sin, 0, sizeof(null_sin));
+
+       sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA];
+       printf("\tinet %s ", inet_ntoa(sin->sin_addr));
+
+       if (flags & IFF_POINTOPOINT) {
+               /* note RTAX_BRD overlap with IFF_BROADCAST */
+               sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD];
+               if (!sin)
+                       sin = &null_sin;
+               printf("--> %s ", inet_ntoa(sin->sin_addr));
+       }
+
+       sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK];
+       if (!sin)
+               sin = &null_sin;
+       printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
+
+       if (flags & IFF_BROADCAST) {
+               /* note RTAX_BRD overlap with IFF_POINTOPOINT */
+               sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD];
+               if (sin && sin->sin_addr.s_addr != 0)
+                       printf("broadcast %s", inet_ntoa(sin->sin_addr));
+       }
+       putchar('\n');
+}
+
+void
+ether_status(s, info)
+       int s ;
+       struct rt_addrinfo *info;
+{
+       char *cp;
+       int n;
+       struct sockaddr_dl *sdl = (struct sockaddr_dl *)info;
+
+       cp = (char *)LLADDR(sdl);
+       if ((n = sdl->sdl_alen) > 0) {
+               if (sdl->sdl_type == IFT_ETHER)
+                       printf ("\tether ");
+               else
+                       printf ("\tlladdr ");
+               while (--n >= 0)
+                       printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' ');
+               putchar('\n');
+       }
+}
+
+void
+Perror(cmd)
+       const char *cmd;
+{
+       switch (errno) {
+
+       case ENXIO:
+               errx(1, "%s: no such interface", cmd);
+               break;
+
+       case EPERM:
+               errx(1, "%s: permission denied", cmd);
+               break;
+
+       default:
+               err(1, "%s", cmd);
+       }
+}
+
+#define SIN(x) ((struct sockaddr_in *) &(x))
+struct sockaddr_in *sintab[] = {
+SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
+SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
+
+void
+in_getaddr(s, which)
+       const char *s;
+       int which;
+{
+       register struct sockaddr_in *sin = sintab[which];
+       struct hostent *hp;
+       struct netent *np;
+
+       sin->sin_len = sizeof(*sin);
+       if (which != MASK)
+               sin->sin_family = AF_INET;
+
+       if (inet_aton(s, &sin->sin_addr))
+               return;
+       if ((hp = gethostbyname(s)) != 0)
+               bcopy(hp->h_addr, (char *)&sin->sin_addr, 
+                   MIN(hp->h_length, sizeof(sin->sin_addr)));
+       else if ((np = getnetbyname(s)) != 0)
+               sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
+       else
+               errx(1, "%s: bad value", s);
+}
+
+/*
+ * Print a value a la the %b format of the kernel's printf
+ */
+void
+printb(s, v, bits)
+       const char *s;
+       register unsigned v;
+       register const char *bits;
+{
+       register int i, any = 0;
+       register char c;
+
+       if (bits && *bits == 8)
+               printf("%s=%o", s, v);
+       else
+               printf("%s=%x", s, v);
+       bits++;
+       if (bits) {
+               putchar('<');
+               while ((i = *bits++) != '\0') {
+                       if (v & (1 << (i-1))) {
+                               if (any)
+                                       putchar(',');
+                               any = 1;
+                               for (; (c = *bits) > 32; bits++)
+                                       putchar(c);
+                       } else
+                               for (; *bits > 32; bits++)
+                                       ;
+               }
+               putchar('>');
+       }
+}
+
+
diff --git a/ifconfig.tproj/ifconfig.h b/ifconfig.tproj/ifconfig.h
new file mode 100644 (file)
index 0000000..a088b7a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1997 Peter Wemm.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed for the FreeBSD Project
+ *     by Peter Wemm.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * so there!
+ *
+ * $Id: ifconfig.h,v 1.1.1.1 2000/01/11 01:48:49 wsanchez Exp $
+ */
+
+extern struct ifreq ifr;
+
+extern char name[32];  /* name of interface */
+extern int allmedia;
+struct afswtch;
+
+extern void setmedia(const char *, int, int, const struct afswtch *rafp);
+extern void setmediaopt(const char *, int, int, const struct afswtch *rafp);
+extern void unsetmediaopt(const char *, int, int, const struct afswtch *rafp);
+extern void media_status(int s, struct rt_addrinfo *);
diff --git a/ifconfig.tproj/ifmedia.c b/ifconfig.tproj/ifmedia.c
new file mode 100644 (file)
index 0000000..1657c21
--- /dev/null
@@ -0,0 +1,554 @@
+/*     $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $      */
+/* $FreeBSD: src/sbin/ifconfig/ifmedia.c,v 1.6 1999/08/28 00:13:08 peter Exp $ */
+
+/*
+ * Copyright (c) 1997 Jason R. Thorpe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed for the NetBSD Project
+ *     by Jason R. Thorpe.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/if_media.h>
+#include <net/route.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+static void    domediaopt __P((const char *, int, int));
+static int     get_media_subtype __P((int, const char *));
+static int     get_media_options __P((int, const char *));
+static int     lookup_media_word __P((struct ifmedia_description *, const char *));
+static void    print_media_word __P((int));
+
+void
+media_status(s, info)
+       int s;
+       struct rt_addrinfo *info;
+{
+       struct ifmediareq ifmr;
+       int *media_list, i;
+
+       (void) memset(&ifmr, 0, sizeof(ifmr));
+       (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
+
+       if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+               /*
+                * Interface doesn't support SIOC{G,S}IFMEDIA.
+                */
+               return;
+       }
+
+       if (ifmr.ifm_count == 0) {
+               //warnx("%s: no media types?", name);
+               return;
+       }
+
+       media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
+       if (media_list == NULL)
+               err(1, "malloc");
+       ifmr.ifm_ulist = media_list;
+
+       if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
+               err(1, "SIOCGIFMEDIA");
+
+       printf("\tmedia: ");
+       print_media_word(ifmr.ifm_current);
+       if (ifmr.ifm_active != ifmr.ifm_current) {
+               putchar(' ');
+               putchar('(');
+               print_media_word(ifmr.ifm_active);
+               putchar(')');
+       }
+
+       if (ifmr.ifm_status & IFM_AVALID) {
+               printf(" status: ");
+#if 0
+               switch (IFM_TYPE(ifmr.ifm_active)) {
+               case IFM_ETHER:
+                       if (ifmr.ifm_status & IFM_ACTIVE)
+                               printf("active");
+                       else
+                               printf("no carrier");
+                       break;
+
+               case IFM_FDDI:
+               case IFM_TOKEN:
+                       if (ifmr.ifm_status & IFM_ACTIVE)
+                               printf("inserted");
+                       else
+                               printf("no ring");
+                       break;
+               }
+#endif 0
+               if (ifmr.ifm_status & IFM_ACTIVE)
+                   printf("active");
+               else
+                   printf("inactive");
+       }
+
+       putchar('\n');
+
+       if (ifmr.ifm_count > 0) {
+               printf("\tsupported media:");
+               for (i = 0; i < ifmr.ifm_count; i++) {
+                       putchar(' ');
+                       print_media_word(media_list[i]);
+               }
+               putchar('\n');
+       }
+
+       free(media_list);
+}
+
+void
+setmedia(val, d, s, afp)
+       const char *val;
+       int d;
+       int s;
+       const struct afswtch *afp;
+{
+       struct ifmediareq ifmr;
+       int first_type, subtype;
+
+       (void) memset(&ifmr, 0, sizeof(ifmr));
+       (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
+
+       ifmr.ifm_count = 1;
+       ifmr.ifm_ulist = &first_type;
+       if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+               /*
+                * If we get E2BIG, the kernel is telling us
+                * that there are more, so we can ignore it.
+                */
+               if (errno != E2BIG)
+                       err(1, "SIOCGIFMEDIA");
+       }
+
+       if (ifmr.ifm_count == 0)
+               errx(1, "%s: no media types?", name);
+
+       /*
+        * We are primarily concerned with the top-level type.
+        * However, "current" may be only IFM_NONE, so we just look
+        * for the top-level type in the first "supported type"
+        * entry.
+        *
+        * (I'm assuming that all supported media types for a given
+        * interface will be the same top-level type..)
+        */
+       subtype = get_media_subtype(IFM_TYPE(first_type), val);
+
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
+           IFM_TYPE(first_type) | subtype;
+
+       if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
+               err(1, "SIOCSIFMEDIA");
+}
+
+void
+setmediaopt(val, d, s, afp)
+       const char *val;
+       int d;
+       int s;
+       const struct afswtch *afp;
+{
+
+       domediaopt(val, 0, s);
+}
+
+void
+unsetmediaopt(val, d, s, afp)
+       const char *val;
+       int d;
+       int s;
+       const struct afswtch *afp;
+{
+
+       domediaopt(val, 1, s);
+}
+
+static void
+domediaopt(val, clear, s)
+       const char *val;
+       int clear;
+       int s;
+{
+       struct ifmediareq ifmr;
+       int *mwords, options;
+
+       (void) memset(&ifmr, 0, sizeof(ifmr));
+       (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
+
+       /*
+        * We must go through the motions of reading all
+        * supported media because we need to know both
+        * the current media type and the top-level type.
+        */
+
+       if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
+               err(1, "SIOCGIFMEDIA");
+
+       if (ifmr.ifm_count == 0)
+               errx(1, "%s: no media types?", name);
+
+       mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
+       if (mwords == NULL)
+               err(1, "malloc");
+
+       ifmr.ifm_ulist = mwords;
+       if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
+               err(1, "SIOCGIFMEDIA");
+
+       options = get_media_options(IFM_TYPE(mwords[0]), val);
+
+       free(mwords);
+
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       ifr.ifr_media = ifmr.ifm_current;
+       if (clear)
+               ifr.ifr_media &= ~options;
+       else
+               ifr.ifr_media |= options;
+
+       if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
+               err(1, "SIOCSIFMEDIA");
+}
+
+/**********************************************************************
+ * A good chunk of this is duplicated from sys/net/ifmedia.c
+ **********************************************************************/
+
+static struct ifmedia_description ifm_type_descriptions[] =
+    IFM_TYPE_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
+    IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
+    IFM_SUBTYPE_ETHERNET_ALIASES;
+
+static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
+    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
+    IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
+    IFM_SUBTYPE_TOKENRING_ALIASES;
+
+static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
+    IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
+    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_fddi_aliases[] =
+    IFM_SUBTYPE_FDDI_ALIASES;
+
+static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
+    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
+    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
+    IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_shared_descriptions[] =
+    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_shared_aliases[] =
+    IFM_SUBTYPE_SHARED_ALIASES;
+
+static struct ifmedia_description ifm_shared_option_descriptions[] =
+    IFM_SHARED_OPTION_DESCRIPTIONS;
+
+struct ifmedia_type_to_subtype {
+       struct {
+               struct ifmedia_description *desc;
+               int alias;
+       } subtypes[5];
+       struct {
+               struct ifmedia_description *desc;
+               int alias;
+       } options[3];
+};
+
+/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
+static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
+       {
+               {
+                       { &ifm_subtype_shared_descriptions[0], 0 },
+                       { &ifm_subtype_shared_aliases[0], 1 },
+                       { &ifm_subtype_ethernet_descriptions[0], 0 },
+                       { &ifm_subtype_ethernet_aliases[0], 1 },
+                       { NULL, 0 },
+               },
+               {
+                       { &ifm_shared_option_descriptions[0], 0 },
+                       { &ifm_subtype_ethernet_option_descriptions[0], 1 },
+                       { NULL, 0 },
+               },
+       },
+       {
+               {
+                       { &ifm_subtype_shared_descriptions[0], 0 },
+                       { &ifm_subtype_shared_aliases[0], 1 },
+                       { &ifm_subtype_tokenring_descriptions[0], 0 },
+                       { &ifm_subtype_tokenring_aliases[0], 1 },
+                       { NULL, 0 },
+               },
+               {
+                       { &ifm_shared_option_descriptions[0], 0 },
+                       { &ifm_subtype_tokenring_option_descriptions[0], 1 },
+                       { NULL, 0 },
+               },
+       },
+       {
+               {
+                       { &ifm_subtype_shared_descriptions[0], 0 },
+                       { &ifm_subtype_shared_aliases[0], 1 },
+                       { &ifm_subtype_fddi_descriptions[0], 0 },
+                       { &ifm_subtype_fddi_aliases[0], 1 },
+                       { NULL, 0 },
+               },
+               {
+                       { &ifm_shared_option_descriptions[0], 0 },
+                       { &ifm_subtype_fddi_option_descriptions[0], 1 },
+                       { NULL, 0 },
+               },
+       },
+       {
+               {
+                       { &ifm_subtype_shared_descriptions[0], 0 },
+                       { &ifm_subtype_shared_aliases[0], 1 },
+                       { &ifm_subtype_ieee80211_descriptions[0], 0 },
+                       { NULL, 0 },
+               },
+               {
+                       { &ifm_shared_option_descriptions[0], 0 },
+                       { &ifm_subtype_ieee80211_option_descriptions[0], 1 },
+                       { NULL, 0 },
+               },
+       },
+};
+
+static int
+get_media_subtype(type, val)
+       int type;
+       const char *val;
+{
+       struct ifmedia_description *desc;
+       struct ifmedia_type_to_subtype *ttos;
+       int rval, i;
+
+       /* Find the top-level interface type. */
+       for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+           desc->ifmt_string != NULL; desc++, ttos++)
+               if (type == desc->ifmt_word)
+                       break;
+       if (desc->ifmt_string == NULL)
+               errx(1, "unknown media type 0x%x", type);
+
+       for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
+               rval = lookup_media_word(ttos->subtypes[i].desc, val);
+               if (rval != -1)
+                       return (rval);
+       }
+       errx(1, "unknown media subtype: %s", val);
+       /* NOTREACHED */
+}
+
+static int
+get_media_options(type, val)
+       int type;
+       const char *val;
+{
+       struct ifmedia_description *desc;
+       struct ifmedia_type_to_subtype *ttos;
+       char *optlist, *optptr;
+       int option = 0, i, rval = 0;
+
+       /* We muck with the string, so copy it. */
+       optlist = strdup(val);
+       if (optlist == NULL)
+               err(1, "strdup");
+
+       /* Find the top-level interface type. */
+       for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+           desc->ifmt_string != NULL; desc++, ttos++)
+               if (type == desc->ifmt_word)
+                       break;
+       if (desc->ifmt_string == NULL)
+               errx(1, "unknown media type 0x%x", type);
+
+       /*
+        * Look up the options in the user-provided comma-separated
+        * list.
+        */
+       optptr = optlist;
+       for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
+               for (i = 0; ttos->options[i].desc != NULL; i++) {
+                       option = lookup_media_word(ttos->options[i].desc, optptr);
+                       if (option != -1)
+                               break;
+               }
+               if (option == 0)
+                       errx(1, "unknown option: %s", optptr);
+               rval |= option;
+       }
+
+       free(optlist);
+       return (rval);
+}
+
+static int
+lookup_media_word(desc, val)
+       struct ifmedia_description *desc;
+       const char *val;
+{
+
+       for (; desc->ifmt_string != NULL; desc++)
+               if (strcasecmp(desc->ifmt_string, val) == 0)
+                       return (desc->ifmt_word);
+
+       return (-1);
+}
+
+static void
+print_media_word(ifmw)
+       int ifmw;
+{
+       struct ifmedia_description *desc;
+       struct ifmedia_type_to_subtype *ttos;
+       int seen_option = 0, i;
+
+       /* Find the top-level interface type. */
+       for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+           desc->ifmt_string != NULL; desc++, ttos++)
+               if (IFM_TYPE(ifmw) == desc->ifmt_word)
+                       break;
+       if (desc->ifmt_string == NULL) {
+               printf("<unknown type>");
+               return;
+       }
+
+       /*
+        * Don't print the top-level type; it's not like we can
+        * change it, or anything.
+        */
+
+       /* Find subtype. */
+       for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
+               if (ttos->subtypes[i].alias)
+                       continue;
+               for (desc = ttos->subtypes[i].desc;
+                   desc->ifmt_string != NULL; desc++) {
+                       if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
+                               goto got_subtype;
+               }
+       }
+
+       /* Falling to here means unknown subtype. */
+       printf("<unknown subtype>");
+       return;
+
+ got_subtype:
+       printf("%s", desc->ifmt_string);
+
+       /* Find options. */
+       for (i = 0; ttos->options[i].desc != NULL; i++) {
+               if (ttos->options[i].alias)
+                       continue;
+               for (desc = ttos->options[i].desc;
+                   desc->ifmt_string != NULL; desc++) {
+                       if (ifmw & desc->ifmt_word) {
+                               if (seen_option == 0)
+                                       printf(" <");
+                               printf("%s%s", seen_option++ ? "," : "",
+                                   desc->ifmt_string);
+                       }
+               }
+       }
+       printf("%s", seen_option ? ">" : "");
+}
+
+/**********************************************************************
+ * ...until here.
+ **********************************************************************/
diff --git a/inetd.tproj/Makefile b/inetd.tproj/Makefile
new file mode 100644 (file)
index 0000000..bd27a46
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = inetd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = inetd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble inetd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/inetd.tproj/Makefile.postamble b/inetd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..f5c79e2
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
diff --git a/inetd.tproj/Makefile.preamble b/inetd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2c9003c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/inetd.tproj/PB.project b/inetd.tproj/PB.project
new file mode 100644 (file)
index 0000000..2eafcda
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pathnames.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (inetd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, inetd.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = inetd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/inetd.tproj/inetd.8 b/inetd.tproj/inetd.8
new file mode 100644 (file)
index 0000000..cc11efe
--- /dev/null
@@ -0,0 +1,381 @@
+.\" Copyright (c) 1985, 1991, 1993, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)inetd.8    8.4 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt INETD 8
+.Os BSD 4.4
+.Sh NAME
+.Nm inetd
+.Nd internet
+.Dq super-server
+.Sh SYNOPSIS
+.Nm inetd
+.Op Fl d
+.Op Fl R Ar rate
+.Op Ar configuration file
+.Sh DESCRIPTION
+The
+.Nm inetd
+program
+should be run at boot time by
+.Pa /etc/rc
+(see
+.Xr rc 8 ) .
+It then listens for connections on certain
+internet sockets.  When a connection is found on one
+of its sockets, it decides what service the socket
+corresponds to, and invokes a program to service the request.
+The server program is invoked with the service socket
+as its standard input, output and error descriptors.
+After the program is
+finished,
+.Nm inetd
+continues to listen on the socket (except in some cases which
+will be described below).  Essentially,
+.Nm inetd
+allows running one daemon to invoke several others,
+reducing load on the system.
+.Pp
+The options available for
+.Nm inetd:
+.Bl -tag -width Ds
+.It Fl d
+Turns on debugging.
+.It Fl R Ar rate
+Specifies the maximum number of times a service can be invoked
+in one minute; the default is 1000.
+.El
+.Pp
+Upon execution,
+.Nm inetd
+reads its configuration information from a configuration
+file which, by default, is
+.Pa /etc/inetd.conf .
+There must be an entry for each field of the configuration
+file, with entries for each field separated by a tab or
+a space.  Comments are denoted by a ``#'' at the beginning
+of a line.  There must be an entry for each field.  The
+fields of the configuration file are as follows:
+.Pp
+.Bd -unfilled -offset indent -compact
+service name
+socket type
+protocol
+wait/nowait
+user
+server program
+server program arguments
+.Ed
+.Pp
+There are two types of services that 
+.Nm inetd
+can start: standard and TCPMUX.
+A standard service has a well-known port assigned to it;
+it may be a service that implements an official Internet standard or is a
+BSD-specific service.
+As described in 
+.Tn RFC 1078 ,
+TCPMUX services are nonstandard services that do not have a 
+well-known port assigned to them.
+They are invoked from
+.Nm inetd 
+when a program connects to the
+.Dq tcpmux
+well-known port and specifies
+the service name.  
+This feature is useful for adding locally-developed servers.
+.Pp
+The
+.Em service-name
+entry is the name of a valid service in
+the file
+.Pa /etc/services .
+For
+.Dq internal
+services (discussed below), the service
+name
+.Em must
+be the official name of the service (that is, the first entry in
+.Pa /etc/services ) .
+For TCPMUX services, the value of the
+.Em service-name
+field consists of the string
+.Dq tcpmux
+followed by a slash and the
+locally-chosen service name. 
+The service names listed in 
+.Pa /etc/services
+and the name 
+.Dq help
+are reserved.
+Try to choose unique names for your TCPMUX services by prefixing them with
+your organization's name and suffixing them with a version number.
+.Pp
+The
+.Em socket-type
+should be one of
+.Dq stream ,
+.Dq dgram ,
+.Dq raw ,
+.Dq rdm ,
+or
+.Dq seqpacket ,
+depending on whether the socket is a stream, datagram, raw,
+reliably delivered message, or sequenced packet socket.
+TCPMUX services must use 
+.Dq stream .
+.Pp
+The
+.Em protocol
+must be a valid protocol as given in
+.Pa /etc/protocols .
+Examples might be
+.Dq tcp
+or
+.Dq udp .
+TCPMUX services must use 
+.Dq tcp .
+.Pp
+The
+.Em wait/nowait
+entry specifies whether the server that is invoked by inetd will take over
+the socket associated with the service access point, and thus whether
+.Nm inetd
+should wait for the server to exit before listening for new service
+requests.
+Datagram servers must use
+.Dq wait ,
+as they are always invoked with the original datagram socket bound
+to the specified service address.
+These servers must read at least one datagram from the socket
+before exiting.
+If a datagram server connects
+to its peer, freeing the socket so
+.Nm inetd
+can received further messages on the socket, it is said to be
+a
+.Dq multi-threaded
+server;
+it should read one datagram from the socket and create a new socket
+connected to the peer.
+It should fork, and the parent should then exit
+to allow
+.Nm inetd
+to check for new service requests to spawn new servers.
+Datagram servers which process all incoming datagrams
+on a socket and eventually time out are said to be
+.Dq single-threaded .
+.Xr Comsat 8 ,
+.Pq Xr biff 1
+and
+.Xr talkd 8
+are both examples of the latter type of
+datagram server.
+.Xr Tftpd 8
+is an example of a multi-threaded datagram server.
+.Pp
+Servers using stream sockets generally are multi-threaded and
+use the
+.Dq nowait
+entry.
+Connection requests for these services are accepted by
+.Nm inetd ,
+and the server is given only the newly-accepted socket connected
+to a client of the service.
+Most stream-based services operate in this manner.
+Stream-based servers that use
+.Dq wait
+are started with the listening service socket, and must accept
+at least one connection request before exiting.
+Such a server would normally accept and process incoming connection
+requests until a timeout.
+TCPMUX services must use 
+.Dq nowait .
+.Pp
+The
+.Em user
+entry should contain the user name of the user as whom the server
+should run.  This allows for servers to be given less permission
+than root.
+.Pp
+The
+.Em server-program
+entry should contain the pathname of the program which is to be
+executed by
+.Nm inetd
+when a request is found on its socket.  If
+.Nm inetd
+provides this service internally, this entry should
+be
+.Dq internal .
+.Pp
+The
+.Em server program arguments
+should be just as arguments
+normally are, starting with argv[0], which is the name of
+the program.  If the service is provided internally, the
+word
+.Dq internal
+should take the place of this entry.
+.Pp
+The
+.Nm inetd
+program
+provides several
+.Dq trivial
+services internally by use of
+routines within itself.  These services are
+.Dq echo ,
+.Dq discard ,
+.Dq chargen
+(character generator),
+.Dq daytime
+(human readable time), and
+.Dq time
+(machine readable time,
+in the form of the number of seconds since midnight, January
+1, 1900).  All of these services are tcp based.  For
+details of these services, consult the appropriate
+.Tn RFC
+from the Network Information Center.
+.Pp
+The
+.Nm inetd
+program
+rereads its configuration file when it receives a hangup signal,
+.Dv SIGHUP .
+Services may be added, deleted or modified when the configuration file
+is reread.
+Except when started in debugging mode,
+.Nm
+records its process ID in the file
+.Pa /var/run/inetd.pid
+to assist in reconfiguration.
+.Sh TCPMUX
+.Pp
+.Tn RFC 1078 
+describes the TCPMUX protocol:
+``A TCP client connects to a foreign host on TCP port 1.  It sends the
+service name followed by a carriage-return line-feed <CRLF>.  The
+service name is never case sensitive.  The server replies with a
+single character indicating positive (+) or negative (\-)
+acknowledgment, immediately followed by an optional message of
+explanation, terminated with a <CRLF>.  If the reply was positive,
+the selected protocol begins; otherwise the connection is closed.''
+The program is passed the TCP connection as file descriptors 0 and 1.
+.Pp
+If the TCPMUX service name begins with a ``+'',
+.Nm inetd
+returns the positive reply for the program.
+This allows you to invoke programs that use stdin/stdout
+without putting any special server code in them.
+.Pp
+The special service name
+.Dq help
+causes
+.Nm inetd
+to list TCPMUX services in
+.Pa inetd.conf .
+.ne 1i
+.Sh "EXAMPLES"
+.Pp
+Here are several example service entries for the various types of services:
+.Bd -literal
+ftp           stream  tcp   nowait root  /usr/libexec/ftpd       ftpd -l
+ntalk         dgram   udp   wait   root  /usr/libexec/ntalkd     ntalkd
+tcpmux/+date  stream  tcp   nowait guest /bin/date               date
+tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook
+.Ed
+.Sh "ERROR MESSAGES"
+The
+.Nm inetd
+server
+logs error messages using
+.Xr syslog 3 .
+Important error messages and their explanations are:
+.Bd -literal
+\fIservice\fP/\fIprotocol\fP server failing (looping), service terminated.
+.Ed
+The number of requests for the specified service in the past minute
+exceeded the limit. The limit exists to prevent a broken program
+or a malicious user from swamping the system.
+This message may occur for several reasons:
+1) there are lots of hosts requesting the service within a short time period,
+2) a 'broken' client program is requesting the service too frequently,
+3) a malicious user is running a program to invoke the service in
+a 'denial of service' attack, or
+4) the invoked service program has an error that causes clients
+to retry quickly.
+Use the
+.Op Fl R 
+option,
+as described above, to change the rate limit.
+Once the limit is reached, the service will be
+reenabled automatically in 10 minutes.
+.sp
+.Bd -literal
+\fIservice\fP/\fIprotocol\fP: No such user '\fIuser\fP', service ignored
+\fIservice\fP/\fIprotocol\fP: getpwnam: \fIuser\fP: No such user
+.Ed
+No entry for 
+.Em user
+exists in the 
+.Pa passwd
+file. The first message
+occurs when
+.Nm inetd
+(re)reads the configuration file. The second message occurs when the
+service is invoked.
+.sp
+.Bd -literal
+\fIservice\fP: can't set uid \fInumber\fP
+\fIservice\fP: can't set gid \fInumber\fP
+.Ed
+The user or group ID for the entry's 
+.Em user
+is invalid.
+.Sh SEE ALSO
+.Xr comsat 8 ,
+.Xr fingerd 8 ,
+.Xr ftpd 8 ,
+.Xr rexecd 8 ,
+.Xr rlogind 8 ,
+.Xr rshd 8 ,
+.Xr telnetd 8 ,
+.Xr tftpd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+TCPMUX is based on code and documentation by Mark Lottor.
diff --git a/inetd.tproj/inetd.c b/inetd.tproj/inetd.c
new file mode 100644 (file)
index 0000000..1b93a68
--- /dev/null
@@ -0,0 +1,1293 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)inetd.c    8.4 (Berkeley) 4/13/94";
+#endif /* not lint */
+
+/*
+ * Inetd - Internet super-server
+ *
+ * This program invokes all internet services as needed.  Connection-oriented
+ * services are invoked each time a connection is made, by creating a process.
+ * This process is passed the connection as file descriptor 0 and is expected
+ * to do a getpeername to find out the source host and port.
+ *
+ * Datagram oriented services are invoked when a datagram
+ * arrives; a process is created and passed a pending message
+ * on file descriptor 0.  Datagram servers may either connect
+ * to their peer, freeing up the original socket for inetd
+ * to receive further messages on, or ``take over the socket'',
+ * processing all arriving datagrams and, eventually, timing
+ * out.         The first type of server is said to be ``multi-threaded'';
+ * the second type of server ``single-threaded''. 
+ *
+ * Inetd uses a configuration file which is read at startup
+ * and, possibly, at some later time in response to a hangup signal.
+ * The configuration file is ``free format'' with fields given in the
+ * order shown below.  Continuation lines for an entry must being with
+ * a space or tab.  All fields must be present in each entry.
+ *
+ *     service name                    must be in /etc/services or must
+ *                                     name a tcpmux service
+ *     socket type                     stream/dgram/raw/rdm/seqpacket
+ *     protocol                        must be in /etc/protocols
+ *     wait/nowait                     single-threaded/multi-threaded
+ *     user                            user to run daemon as
+ *     server program                  full path name
+ *     server program arguments        maximum of MAXARGS (20)
+ *
+ * TCP services without official port numbers are handled with the
+ * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
+ * requests. When a connection is made from a foreign host, the service
+ * requested is passed to tcpmux, which looks it up in the servtab list
+ * and returns the proper entry for the service. Tcpmux returns a
+ * negative reply if the service doesn't exist, otherwise the invoked
+ * server is expected to return the positive reply if the service type in
+ * inetd.conf file has the prefix "tcpmux/". If the service type has the
+ * prefix "tcpmux/+", tcpmux will return the positive reply for the
+ * process; this is for compatibility with older server code, and also
+ * allows you to invoke programs that use stdin/stdout without putting any
+ * special server code in them. Services that use tcpmux are "nowait"
+ * because they do not have a well-known port and hence cannot listen
+ * for new requests.
+ *
+ * Comment lines are indicated by a `#' in column 1.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+#define        TOOMANY         100             /* don't start more than TOOMANY */
+#define        CNT_INTVL       60              /* servers in CNT_INTVL sec. */
+#define        RETRYTIME       (60*10)         /* retry after bind or server fail */
+
+#define        SIGBLOCK        (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
+
+
+int    debug = 0;
+int    nsock, maxsock;
+fd_set allsock;
+int    options;
+int    timingout;
+int    toomany = TOOMANY;
+struct servent *sp;
+
+struct servtab {
+       char    *se_service;            /* name of service */
+       int     se_socktype;            /* type of socket to use */
+       char    *se_proto;              /* protocol used */
+       short   se_wait;                /* single threaded server */
+       short   se_checked;             /* looked at during merge */
+       char    *se_user;               /* user name to run as */
+       struct  biltin *se_bi;          /* if built-in, description */
+       char    *se_server;             /* server program */
+#define        MAXARGV 20
+       char    *se_argv[MAXARGV+1];    /* program arguments */
+       int     se_fd;                  /* open descriptor */
+       int     se_type;                /* type */
+       struct  sockaddr_in se_ctrladdr;/* bound address */
+       int     se_count;               /* number started since se_time */
+       struct  timeval se_time;        /* start of se_count */
+       struct  servtab *se_next;
+} *servtab;
+
+#define NORM_TYPE      0
+#define MUX_TYPE       1
+#define MUXPLUS_TYPE   2
+#define ISMUX(sep)     (((sep)->se_type == MUX_TYPE) || \
+                        ((sep)->se_type == MUXPLUS_TYPE))
+#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE)
+
+
+void           chargen_dg __P((int, struct servtab *));
+void           chargen_stream __P((int, struct servtab *));
+void           close_sep __P((struct servtab *));
+void           config __P((int));
+void           daytime_dg __P((int, struct servtab *));
+void           daytime_stream __P((int, struct servtab *));
+void           discard_dg __P((int, struct servtab *));
+void           discard_stream __P((int, struct servtab *));
+void           echo_dg __P((int, struct servtab *));
+void           echo_stream __P((int, struct servtab *));
+void           endconfig __P((void));
+struct servtab *enter __P((struct servtab *));
+void           freeconfig __P((struct servtab *));
+struct servtab *getconfigent __P((void));
+void           machtime_dg __P((int, struct servtab *));
+void           machtime_stream __P((int, struct servtab *));
+char          *newstr __P((char *));
+char          *nextline __P((FILE *));
+void           print_service __P((char *, struct servtab *));
+void           reapchild __P((int));
+void           retry __P((int));
+int            setconfig __P((void));
+void           setup __P((struct servtab *));
+char          *sskip __P((char **));
+char          *skip __P((char **));
+struct servtab *tcpmux __P((int));
+
+struct biltin {
+       char    *bi_service;            /* internally provided service name */
+       int     bi_socktype;            /* type of socket supported */
+       short   bi_fork;                /* 1 if should fork before call */
+       short   bi_wait;                /* 1 if should wait for child */
+       void    (*bi_fn)();             /* function which performs it */
+} biltins[] = {
+       /* Echo received data */
+       { "echo",       SOCK_STREAM,    1, 0,   echo_stream },
+       { "echo",       SOCK_DGRAM,     0, 0,   echo_dg },
+
+       /* Internet /dev/null */
+       { "discard",    SOCK_STREAM,    1, 0,   discard_stream },
+       { "discard",    SOCK_DGRAM,     0, 0,   discard_dg },
+
+       /* Return 32 bit time since 1970 */
+       { "time",       SOCK_STREAM,    0, 0,   machtime_stream },
+       { "time",       SOCK_DGRAM,     0, 0,   machtime_dg },
+
+       /* Return human-readable time */
+       { "daytime",    SOCK_STREAM,    0, 0,   daytime_stream },
+       { "daytime",    SOCK_DGRAM,     0, 0,   daytime_dg },
+
+       /* Familiar character generator */
+       { "chargen",    SOCK_STREAM,    1, 0,   chargen_stream },
+       { "chargen",    SOCK_DGRAM,     0, 0,   chargen_dg },
+
+       { "tcpmux",     SOCK_STREAM,    1, 0,   (void (*)())tcpmux },
+
+       { NULL }
+};
+
+#define NUMINT (sizeof(intab) / sizeof(struct inent))
+char   *CONFIG = _PATH_INETDCONF;
+char   *pid_file = _PATH_INETDPID;
+char   **Argv;
+char   *LastArg;
+
+int
+main(argc, argv, envp)
+       int argc;
+       char *argv[], *envp[];
+{
+       struct servtab *sep;
+       struct passwd *pwd;
+       struct sigvec sv;
+       int tmpint, ch, dofork;
+       pid_t pid;
+       char buf[50];
+
+       Argv = argv;
+       if (envp == 0 || *envp == 0)
+               envp = argv;
+       while (*envp)
+               envp++;
+       LastArg = envp[-1] + strlen(envp[-1]);
+
+       openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
+
+       while ((ch = getopt(argc, argv, "dR:p:")) != EOF)
+               switch(ch) {
+               case 'd':
+                       debug = 1;
+                       options |= SO_DEBUG;
+                       break;
+               case 'R': {     /* invocation rate */
+                       char *p;
+
+                       tmpint = strtol(optarg, &p, 0);
+                       if (tmpint < 1 || *p)
+                               syslog(LOG_ERR,
+                                "-R %s: bad value for service invocation rate",
+                                       optarg);
+                       else
+                               toomany = tmpint;
+                       break;
+               }
+               case 'p': 
+                       pid_file = optarg;
+                       break;
+               case '?':
+               default:
+                       syslog(LOG_ERR,
+                               "usage: inetd [-d] [-R rate] [conf-file]");
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc > 0)
+               CONFIG = argv[0];
+       if (debug == 0) {
+               FILE *fp;
+               daemon(0, 0);
+
+               pid = getpid();
+               fp = fopen(pid_file, "w");
+               if( fp ) {
+                       fprintf(fp, "%ld\n", (long)pid);
+                       fclose(fp);
+               } else {
+                       syslog(LOG_WARNING, "%s: %m", pid_file);
+               }
+       }
+       memset(&sv, 0, sizeof(sv));
+       sv.sv_mask = SIGBLOCK;
+       sv.sv_handler = retry;
+       sigvec(SIGALRM, &sv, (struct sigvec *)0);
+       config(SIGHUP);
+       sv.sv_handler = config;
+       sigvec(SIGHUP, &sv, (struct sigvec *)0);
+       sv.sv_handler = reapchild;
+       sigvec(SIGCHLD, &sv, (struct sigvec *)0);
+
+       {
+               /* space for daemons to overwrite environment for ps */
+#define        DUMMYSIZE       100
+               char dummy[DUMMYSIZE];
+
+               (void)memset(dummy, 'x', sizeof(DUMMYSIZE) - 1);
+               dummy[DUMMYSIZE - 1] = '\0';
+               (void)setenv("inetd_dummy", dummy, 1);
+       }
+
+       for (;;) {
+           int n, ctrl;
+           fd_set readable;
+
+           if (nsock == 0) {
+               (void) sigblock(SIGBLOCK);
+               while (nsock == 0)
+                   sigpause(0L);
+               (void) sigsetmask(0L);
+           }
+           readable = allsock;
+           if ((n = select(maxsock + 1, &readable, (fd_set *)0,
+               (fd_set *)0, (struct timeval *)0)) <= 0) {
+                   if (n < 0 && errno != EINTR) {
+                       syslog(LOG_WARNING, "select: %m");
+                       sleep(1);
+                   }
+                   continue;
+           }
+           for (sep = servtab; n && sep; sep = sep->se_next)
+               if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
+                   n--;
+                   if (debug)
+                           fprintf(stderr, "someone wants %s\n",
+                               sep->se_service);
+                   if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+                           ctrl = accept(sep->se_fd, (struct sockaddr *)0,
+                               (int *)0);
+                           if (debug)
+                                   fprintf(stderr, "accept, ctrl %d\n", ctrl);
+                           if (ctrl < 0) {
+                                   if (errno != EINTR)
+                                           syslog(LOG_WARNING,
+                                               "accept (for %s): %m",
+                                               sep->se_service);
+                                   continue;
+                           }
+                           /*
+                            * Call tcpmux to find the real service to exec.
+                            */
+                           if (sep->se_bi &&
+                               sep->se_bi->bi_fn == (void (*)()) tcpmux) {
+                                   sep = tcpmux(ctrl);
+                                   if (sep == NULL) {
+                                           close(ctrl);
+                                           continue;
+                                   }
+                           }
+                   } else
+                           ctrl = sep->se_fd;
+                   (void) sigblock(SIGBLOCK);
+                   pid = 0;
+                   dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
+                   if (dofork) {
+                           if (sep->se_count++ == 0)
+                               (void)gettimeofday(&sep->se_time,
+                                   (struct timezone *)0);
+                           else if (sep->se_count >= toomany) {
+                               struct timeval now;
+
+                               (void)gettimeofday(&now, (struct timezone *)0);
+                               if (now.tv_sec - sep->se_time.tv_sec >
+                                   CNT_INTVL) {
+                                       sep->se_time = now;
+                                       sep->se_count = 1;
+                               } else {
+                                       syslog(LOG_ERR,
+                       "%s/%s server failing (looping), service terminated",
+                                           sep->se_service, sep->se_proto);
+                                       close_sep(sep);
+                                       sigsetmask(0L);
+                                       if (!timingout) {
+                                               timingout = 1;
+                                               alarm(RETRYTIME);
+                                       }
+                                       continue;
+                               }
+                           }
+                           pid = fork();
+                   }
+                   if (pid < 0) {
+                           syslog(LOG_ERR, "fork: %m");
+                           if (!sep->se_wait &&
+                               sep->se_socktype == SOCK_STREAM)
+                                   close(ctrl);
+                           sigsetmask(0L);
+                           sleep(1);
+                           continue;
+                   }
+                   if (pid && sep->se_wait) {
+                           sep->se_wait = pid;
+                           if (sep->se_fd >= 0) {
+                               FD_CLR(sep->se_fd, &allsock);
+                               nsock--;
+                           }
+                   }
+                   sigsetmask(0L);
+                   if (pid == 0) {
+                           if (debug && dofork)
+                               setsid();
+                           if (dofork) {
+                               if (debug)
+                                       fprintf(stderr, "+ Closing from %d\n",
+                                               maxsock);
+                               for (tmpint = maxsock; tmpint > 2; tmpint--)
+                                       if (tmpint != ctrl)
+                                               close(tmpint);
+                           }
+                           if (sep->se_bi)
+                               (*sep->se_bi->bi_fn)(ctrl, sep);
+                           else {
+                               if (debug)
+                                       fprintf(stderr, "%d execl %s\n",
+                                           getpid(), sep->se_server);
+                               dup2(ctrl, 0);
+                               close(ctrl);
+                               dup2(0, 1);
+                               dup2(0, 2);
+                               if ((pwd = getpwnam(sep->se_user)) == NULL) {
+                                       syslog(LOG_ERR,
+                                           "%s/%s: %s: No such user",
+                                               sep->se_service, sep->se_proto,
+                                               sep->se_user);
+                                       if (sep->se_socktype != SOCK_STREAM)
+                                               recv(0, buf, sizeof (buf), 0);
+                                       _exit(1);
+                               }
+                               if (pwd->pw_uid) {
+                                       if (setgid(pwd->pw_gid) < 0) {
+                                               syslog(LOG_ERR,
+                                                 "%s: can't set gid %d: %m", 
+                                                 sep->se_service, pwd->pw_gid);
+                                               _exit(1);
+                                       }
+                                       (void) initgroups(pwd->pw_name,
+                                                       pwd->pw_gid);
+                                       if (setuid(pwd->pw_uid) < 0) {
+                                               syslog(LOG_ERR,
+                                                 "%s: can't set uid %d: %m", 
+                                                 sep->se_service, pwd->pw_uid);
+                                               _exit(1);
+                                       }
+                               }
+                               execv(sep->se_server, sep->se_argv);
+                               if (sep->se_socktype != SOCK_STREAM)
+                                       recv(0, buf, sizeof (buf), 0);
+                               syslog(LOG_ERR,
+                                   "cannot execute %s: %m", sep->se_server);
+                               _exit(1);
+                           }
+                   }
+                   if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+                           close(ctrl);
+               }
+       }
+}
+
+void
+reapchild(signo)
+       int signo;
+{
+       int status;
+       pid_t pid;
+       struct servtab *sep;
+
+       for (;;) {
+               pid = wait3(&status, WNOHANG, (struct rusage *)0);
+               if (pid <= 0)
+                       break;
+               if (debug)
+                       fprintf(stderr, "%d reaped, status %#x\n", 
+                               pid, status);
+               for (sep = servtab; sep; sep = sep->se_next)
+                       if (sep->se_wait == pid) {
+                               if (status)
+                                       syslog(LOG_WARNING,
+                                           "%s: exit status 0x%x",
+                                           sep->se_server, status);
+                               if (debug)
+                                       fprintf(stderr, "restored %s, fd %d\n",
+                                           sep->se_service, sep->se_fd);
+                               FD_SET(sep->se_fd, &allsock);
+                               nsock++;
+                               sep->se_wait = 1;
+                       }
+       }
+}
+
+void
+config(signo)
+       int signo;
+{
+       struct servtab *sep, *cp, **sepp;
+       struct passwd *pwd;
+       long omask;
+
+       if (!setconfig()) {
+               syslog(LOG_ERR, "%s: %m", CONFIG);
+               return;
+       }
+       for (sep = servtab; sep; sep = sep->se_next)
+               sep->se_checked = 0;
+       while (cp = getconfigent()) {
+               if ((pwd = getpwnam(cp->se_user)) == NULL) {
+                       syslog(LOG_ERR,
+                               "%s/%s: No such user '%s', service ignored",
+                               cp->se_service, cp->se_proto, cp->se_user);
+                       continue;
+               }
+               for (sep = servtab; sep; sep = sep->se_next)
+                       if (strcmp(sep->se_service, cp->se_service) == 0 &&
+                           strcmp(sep->se_proto, cp->se_proto) == 0)
+                               break;
+               if (sep != 0) {
+                       int i;
+
+                       omask = sigblock(SIGBLOCK);
+                       /*
+                        * sep->se_wait may be holding the pid of a daemon
+                        * that we're waiting for.  If so, don't overwrite
+                        * it unless the config file explicitly says don't 
+                        * wait.
+                        */
+                       if (cp->se_bi == 0 && 
+                           (sep->se_wait == 1 || cp->se_wait == 0))
+                               sep->se_wait = cp->se_wait;
+#define SWAP(a, b) { char *c = a; a = b; b = c; }
+                       if (cp->se_user)
+                               SWAP(sep->se_user, cp->se_user);
+                       if (cp->se_server)
+                               SWAP(sep->se_server, cp->se_server);
+                       for (i = 0; i < MAXARGV; i++)
+                               SWAP(sep->se_argv[i], cp->se_argv[i]);
+                       sigsetmask(omask);
+                       freeconfig(cp);
+                       if (debug)
+                               print_service("REDO", sep);
+               } else {
+                       sep = enter(cp);
+                       if (debug)
+                               print_service("ADD ", sep);
+               }
+               sep->se_checked = 1;
+               if (ISMUX(sep)) {
+                       sep->se_fd = -1;
+                       continue;
+               }
+               sp = getservbyname(sep->se_service, sep->se_proto);
+               if (sp == 0) {
+                       syslog(LOG_ERR, "%s/%s: unknown service",
+                           sep->se_service, sep->se_proto);
+                       sep->se_checked = 0;
+                       continue;
+               }
+               if (sp->s_port != sep->se_ctrladdr.sin_port) {
+                       sep->se_ctrladdr.sin_family = AF_INET;
+                       sep->se_ctrladdr.sin_port = sp->s_port;
+                       if (sep->se_fd >= 0)
+                               close_sep(sep);
+               }
+               if (sep->se_fd == -1)
+                       setup(sep);
+       }
+       endconfig();
+       /*
+        * Purge anything not looked at above.
+        */
+       omask = sigblock(SIGBLOCK);
+       sepp = &servtab;
+       while (sep = *sepp) {
+               if (sep->se_checked) {
+                       sepp = &sep->se_next;
+                       continue;
+               }
+               *sepp = sep->se_next;
+               if (sep->se_fd >= 0)
+                       close_sep(sep);
+               if (debug)
+                       print_service("FREE", sep);
+               freeconfig(sep);
+               free((char *)sep);
+       }
+       (void) sigsetmask(omask);
+}
+
+void
+retry(signo)
+       int signo;
+{
+       struct servtab *sep;
+
+       timingout = 0;
+       for (sep = servtab; sep; sep = sep->se_next)
+               if (sep->se_fd == -1)
+                       setup(sep);
+}
+
+void
+setup(sep)
+       struct servtab *sep;
+{
+       int on = 1;
+
+       if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
+               if (debug)
+                       fprintf(stderr, "socket failed on %s/%s: %s\n", 
+                               sep->se_service, sep->se_proto,
+                               strerror(errno));
+               syslog(LOG_ERR, "%s/%s: socket: %m",
+                   sep->se_service, sep->se_proto);
+               return;
+       }
+#define        turnon(fd, opt) \
+setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
+       if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
+           turnon(sep->se_fd, SO_DEBUG) < 0)
+               syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
+       if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
+               syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
+#undef turnon
+       if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
+           sizeof (sep->se_ctrladdr)) < 0) {
+               if (debug)
+                       fprintf(stderr, "bind failed on %s/%s: %s\n",
+                               sep->se_service, sep->se_proto,
+                               strerror(errno));
+               syslog(LOG_ERR, "%s/%s: bind: %m",
+                   sep->se_service, sep->se_proto);
+               (void) close(sep->se_fd);
+               sep->se_fd = -1;
+               if (!timingout) {
+                       timingout = 1;
+                       alarm(RETRYTIME);
+               }
+               return;
+       }
+       if (sep->se_socktype == SOCK_STREAM)
+               listen(sep->se_fd, 10);
+       FD_SET(sep->se_fd, &allsock);
+       nsock++;
+       if (sep->se_fd > maxsock)
+               maxsock = sep->se_fd;
+       if (debug) {
+               fprintf(stderr, "registered %s on %d\n",
+                       sep->se_server, sep->se_fd);
+       }
+}
+
+/*
+ * Finish with a service and its socket.
+ */
+void
+close_sep(sep)
+       struct servtab *sep;
+{
+       if (sep->se_fd >= 0) {
+               nsock--;
+               FD_CLR(sep->se_fd, &allsock);
+               (void) close(sep->se_fd);
+               sep->se_fd = -1;
+       }
+       sep->se_count = 0;
+       /*
+        * Don't keep the pid of this running deamon: when reapchild()
+        * reaps this pid, it would erroneously increment nsock.
+        */
+       if (sep->se_wait > 1)
+               sep->se_wait = 1;
+}
+
+struct servtab *
+enter(cp)
+       struct servtab *cp;
+{
+       struct servtab *sep;
+       long omask;
+
+       sep = (struct servtab *)malloc(sizeof (*sep));
+       if (sep == (struct servtab *)0) {
+               syslog(LOG_ERR, "Out of memory.");
+               exit(-1);
+       }
+       *sep = *cp;
+       sep->se_fd = -1;
+       omask = sigblock(SIGBLOCK);
+       sep->se_next = servtab;
+       servtab = sep;
+       sigsetmask(omask);
+       return (sep);
+}
+
+FILE   *fconfig = NULL;
+struct servtab serv;
+char   line[LINE_MAX];
+
+int
+setconfig()
+{
+
+       if (fconfig != NULL) {
+               fseek(fconfig, 0L, SEEK_SET);
+               return (1);
+       }
+       fconfig = fopen(CONFIG, "r");
+       return (fconfig != NULL);
+}
+
+void
+endconfig()
+{
+       if (fconfig) {
+               (void) fclose(fconfig);
+               fconfig = NULL;
+       }
+}
+
+struct servtab *
+getconfigent()
+{
+       struct servtab *sep = &serv;
+       int argc;
+       char *cp, *arg;
+       static char TCPMUX_TOKEN[] = "tcpmux/";
+#define MUX_LEN                (sizeof(TCPMUX_TOKEN)-1)
+
+more:
+       while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0'))
+               ;
+       if (cp == NULL)
+               return ((struct servtab *)0);
+       /*
+        * clear the static buffer, since some fields (se_ctrladdr,
+        * for example) don't get initialized here.
+        */
+       memset((caddr_t)sep, 0, sizeof *sep);
+       arg = skip(&cp);
+       if (cp == NULL) {
+               /* got an empty line containing just blanks/tabs. */
+               goto more;
+       }
+       if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
+               char *c = arg + MUX_LEN;
+               if (*c == '+') {
+                       sep->se_type = MUXPLUS_TYPE;
+                       c++;
+               } else
+                       sep->se_type = MUX_TYPE;
+               sep->se_service = newstr(c);
+       } else {
+               sep->se_service = newstr(arg);
+               sep->se_type = NORM_TYPE;
+       }
+       arg = sskip(&cp);
+       if (strcmp(arg, "stream") == 0)
+               sep->se_socktype = SOCK_STREAM;
+       else if (strcmp(arg, "dgram") == 0)
+               sep->se_socktype = SOCK_DGRAM;
+       else if (strcmp(arg, "rdm") == 0)
+               sep->se_socktype = SOCK_RDM;
+       else if (strcmp(arg, "seqpacket") == 0)
+               sep->se_socktype = SOCK_SEQPACKET;
+       else if (strcmp(arg, "raw") == 0)
+               sep->se_socktype = SOCK_RAW;
+       else
+               sep->se_socktype = -1;
+       sep->se_proto = newstr(sskip(&cp));
+       arg = sskip(&cp);
+       sep->se_wait = strcmp(arg, "wait") == 0;
+       if (ISMUX(sep)) {
+               /*
+                * Silently enforce "nowait" for TCPMUX services since
+                * they don't have an assigned port to listen on.
+                */
+               sep->se_wait = 0;
+
+               if (strcmp(sep->se_proto, "tcp")) {
+                       syslog(LOG_ERR, 
+                               "%s: bad protocol for tcpmux service %s",
+                               CONFIG, sep->se_service);
+                       goto more;
+               }
+               if (sep->se_socktype != SOCK_STREAM) {
+                       syslog(LOG_ERR, 
+                               "%s: bad socket type for tcpmux service %s",
+                               CONFIG, sep->se_service);
+                       goto more;
+               }
+       }
+       sep->se_user = newstr(sskip(&cp));
+       sep->se_server = newstr(sskip(&cp));
+       if (strcmp(sep->se_server, "internal") == 0) {
+               struct biltin *bi;
+
+               for (bi = biltins; bi->bi_service; bi++)
+                       if (bi->bi_socktype == sep->se_socktype &&
+                           strcmp(bi->bi_service, sep->se_service) == 0)
+                               break;
+               if (bi->bi_service == 0) {
+                       syslog(LOG_ERR, "internal service %s unknown",
+                               sep->se_service);
+                       goto more;
+               }
+               sep->se_bi = bi;
+               sep->se_wait = bi->bi_wait;
+       } else
+               sep->se_bi = NULL;
+       argc = 0;
+       for (arg = skip(&cp); cp; arg = skip(&cp))
+               if (argc < MAXARGV)
+                       sep->se_argv[argc++] = newstr(arg);
+       while (argc <= MAXARGV)
+               sep->se_argv[argc++] = NULL;
+       return (sep);
+}
+
+void
+freeconfig(cp)
+       struct servtab *cp;
+{
+       int i;
+
+       if (cp->se_service)
+               free(cp->se_service);
+       if (cp->se_proto)
+               free(cp->se_proto);
+       if (cp->se_user)
+               free(cp->se_user);
+       if (cp->se_server)
+               free(cp->se_server);
+       for (i = 0; i < MAXARGV; i++)
+               if (cp->se_argv[i])
+                       free(cp->se_argv[i]);
+}
+
+
+/*
+ * Safe skip - if skip returns null, log a syntax error in the
+ * configuration file and exit.
+ */
+char *
+sskip(cpp)
+       char **cpp;
+{
+       char *cp;
+
+       cp = skip(cpp);
+       if (cp == NULL) {
+               syslog(LOG_ERR, "%s: syntax error", CONFIG);
+               exit(-1);
+       }
+       return (cp);
+}
+
+char *
+skip(cpp)
+       char **cpp;
+{
+       char *cp = *cpp;
+       char *start;
+
+again:
+       while (*cp == ' ' || *cp == '\t')
+               cp++;
+       if (*cp == '\0') {
+               int c;
+
+               c = getc(fconfig);
+               (void) ungetc(c, fconfig);
+               if (c == ' ' || c == '\t')
+                       if (cp = nextline(fconfig))
+                               goto again;
+               *cpp = (char *)0;
+               return ((char *)0);
+       }
+       start = cp;
+       while (*cp && *cp != ' ' && *cp != '\t')
+               cp++;
+       if (*cp != '\0')
+               *cp++ = '\0';
+       *cpp = cp;
+       return (start);
+}
+
+char *
+nextline(fd)
+       FILE *fd;
+{
+       char *cp;
+
+       if (fgets(line, sizeof (line), fd) == NULL)
+               return ((char *)0);
+       cp = strchr(line, '\n');
+       if (cp)
+               *cp = '\0';
+       return (line);
+}
+
+char *
+newstr(cp)
+       char *cp;
+{
+       if (cp = strdup(cp ? cp : ""))
+               return (cp);
+       syslog(LOG_ERR, "strdup: %m");
+       exit(-1);
+}
+
+void
+setproctitle(a, s)
+       char *a;
+       int s;
+{
+       int size;
+       char *cp;
+       struct sockaddr_in sin;
+       char buf[80];
+
+       cp = Argv[0];
+       size = sizeof(sin);
+       if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
+               (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
+       else
+               (void) sprintf(buf, "-%s", a); 
+       strncpy(cp, buf, LastArg - cp);
+       cp += strlen(cp);
+       while (cp < LastArg)
+               *cp++ = ' ';
+}
+
+/*
+ * Internet services provided internally by inetd:
+ */
+#define        BUFSIZE 8192
+
+/* ARGSUSED */
+void
+echo_stream(s, sep)            /* Echo service -- echo data back */
+       int s;
+       struct servtab *sep;
+{
+       char buffer[BUFSIZE];
+       int i;
+
+       setproctitle(sep->se_service, s);
+       while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
+           write(s, buffer, i) > 0)
+               ;
+       exit(0);
+}
+
+/* ARGSUSED */
+void
+echo_dg(s, sep)                        /* Echo service -- echo data back */
+       int s;
+       struct servtab *sep;
+{
+       char buffer[BUFSIZE];
+       int i, size;
+       struct sockaddr sa;
+
+       size = sizeof(sa);
+       if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
+               return;
+       (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
+}
+
+/* ARGSUSED */
+void
+discard_stream(s, sep)         /* Discard service -- ignore data */
+       int s;
+       struct servtab *sep;
+{
+       int ret;
+       char buffer[BUFSIZE];
+
+       setproctitle(sep->se_service, s);
+       while (1) {
+               while ((ret = read(s, buffer, sizeof(buffer))) > 0)
+                       ;
+               if (ret == 0 || errno != EINTR)
+                       break;
+       }
+       exit(0);
+}
+
+/* ARGSUSED */
+void
+discard_dg(s, sep)             /* Discard service -- ignore data */
+       int s;
+       struct servtab *sep;
+{
+       char buffer[BUFSIZE];
+
+       (void) read(s, buffer, sizeof(buffer));
+}
+
+#include <ctype.h>
+#define LINESIZ 72
+char ring[128];
+char *endring;
+
+void
+initring()
+{
+       int i;
+
+       endring = ring;
+
+       for (i = 0; i <= 128; ++i)
+               if (isprint(i))
+                       *endring++ = i;
+}
+
+/* ARGSUSED */
+void
+chargen_stream(s, sep)         /* Character generator */
+       int s;
+       struct servtab *sep;
+{
+       int len;
+       char *rs, text[LINESIZ+2];
+
+       setproctitle(sep->se_service, s);
+
+       if (!endring) {
+               initring();
+               rs = ring;
+       }
+
+       text[LINESIZ] = '\r';
+       text[LINESIZ + 1] = '\n';
+       for (rs = ring;;) {
+               if ((len = endring - rs) >= LINESIZ)
+                       memmove(text, rs, LINESIZ);
+               else {
+                       memmove(text, rs, len);
+                       memmove(text + len, ring, LINESIZ - len);
+               }
+               if (++rs == endring)
+                       rs = ring;
+               if (write(s, text, sizeof(text)) != sizeof(text))
+                       break;
+       }
+       exit(0);
+}
+
+/* ARGSUSED */
+void
+chargen_dg(s, sep)             /* Character generator */
+       int s;
+       struct servtab *sep;
+{
+       struct sockaddr sa;
+       static char *rs;
+       int len, size;
+       char text[LINESIZ+2];
+
+       if (endring == 0) {
+               initring();
+               rs = ring;
+       }
+
+       size = sizeof(sa);
+       if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
+               return;
+
+       if ((len = endring - rs) >= LINESIZ)
+               memmove(text, rs, LINESIZ);
+       else {
+               memmove(text, rs, len);
+               memmove(text + len, ring, LINESIZ - len);
+       }
+       if (++rs == endring)
+               rs = ring;
+       text[LINESIZ] = '\r';
+       text[LINESIZ + 1] = '\n';
+       (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
+}
+
+/*
+ * Return a machine readable date and time, in the form of the
+ * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
+ * returns the number of seconds since midnight, Jan 1, 1970,
+ * we must add 2208988800 seconds to this figure to make up for
+ * some seventy years Bell Labs was asleep.
+ */
+
+long
+machtime()
+{
+       struct timeval tv;
+
+       if (gettimeofday(&tv, (struct timezone *)0) < 0) {
+               if (debug)
+                       fprintf(stderr, "Unable to get time of day\n");
+               return (0L);
+       }
+#define        OFFSET ((u_long)25567 * 24*60*60)
+       return (htonl((long)(tv.tv_sec + OFFSET)));
+#undef OFFSET
+}
+
+/* ARGSUSED */
+void
+machtime_stream(s, sep)
+       int s;
+       struct servtab *sep;
+{
+       long result;
+
+       result = machtime();
+       (void) write(s, (char *) &result, sizeof(result));
+}
+
+/* ARGSUSED */
+void
+machtime_dg(s, sep)
+       int s;
+       struct servtab *sep;
+{
+       long result;
+       struct sockaddr sa;
+       int size;
+
+       size = sizeof(sa);
+       if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
+               return;
+       result = machtime();
+       (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
+}
+
+/* ARGSUSED */
+void
+daytime_stream(s, sep)         /* Return human-readable time of day */
+       int s;
+       struct servtab *sep;
+{
+       char buffer[256];
+       time_t clock;
+
+       clock = time((time_t *) 0);
+
+       (void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
+       (void) write(s, buffer, strlen(buffer));
+}
+
+/* ARGSUSED */
+void
+daytime_dg(s, sep)             /* Return human-readable time of day */
+       int s;
+       struct servtab *sep;
+{
+       char buffer[256];
+       time_t clock;
+       struct sockaddr sa;
+       int size;
+
+       clock = time((time_t *) 0);
+
+       size = sizeof(sa);
+       if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
+               return;
+       (void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
+       (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
+}
+
+/*
+ * print_service:
+ *     Dump relevant information to stderr
+ */
+void
+print_service(action, sep)
+       char *action;
+       struct servtab *sep;
+{
+       fprintf(stderr,
+           "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
+           action, sep->se_service, sep->se_proto,
+           sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server);
+}
+
+/*
+ *  Based on TCPMUX.C by Mark K. Lottor November 1988
+ *  sri-nic::ps:<mkl>tcpmux.c
+ */
+
+
+static int             /* # of characters upto \r,\n or \0 */
+getline(fd, buf, len)
+       int fd;
+       char *buf;
+       int len;
+{
+       int count = 0, n;
+
+       do {
+               n = read(fd, buf, len-count);
+               if (n == 0)
+                       return (count);
+               if (n < 0)
+                       return (-1);
+               while (--n >= 0) {
+                       if (*buf == '\r' || *buf == '\n' || *buf == '\0')
+                               return (count);
+                       count++;
+                       buf++;
+               }
+       } while (count < len);
+       return (count);
+}
+
+#define MAX_SERV_LEN   (256+2)         /* 2 bytes for \r\n */
+
+#define strwrite(fd, buf)      (void) write(fd, buf, sizeof(buf)-1)
+
+struct servtab *
+tcpmux(s)
+       int s;
+{
+       struct servtab *sep;
+       char service[MAX_SERV_LEN+1];
+       int len;
+
+       /* Get requested service name */
+       if ((len = getline(s, service, MAX_SERV_LEN)) < 0) {
+               strwrite(s, "-Error reading service name\r\n");
+               return (NULL);
+       }
+       service[len] = '\0';
+
+       if (debug)
+               fprintf(stderr, "tcpmux: someone wants %s\n", service);
+
+       /*
+        * Help is a required command, and lists available services,
+        * one per line.
+        */
+       if (!strcasecmp(service, "help")) {
+               for (sep = servtab; sep; sep = sep->se_next) {
+                       if (!ISMUX(sep))
+                               continue;
+                       (void)write(s,sep->se_service,strlen(sep->se_service));
+                       strwrite(s, "\r\n");
+               }
+               return (NULL);
+       }
+
+       /* Try matching a service in inetd.conf with the request */
+       for (sep = servtab; sep; sep = sep->se_next) {
+               if (!ISMUX(sep))
+                       continue;
+               if (!strcasecmp(service, sep->se_service)) {
+                       if (ISMUXPLUS(sep)) {
+                               strwrite(s, "+Go\r\n");
+                       }
+                       return (sep);
+               }
+       }
+       strwrite(s, "-Service not available\r\n");
+       return (NULL);
+}
diff --git a/inetd.tproj/pathnames.h b/inetd.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..4a7b367
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#define        _PATH_INETDCONF "/etc/inetd.conf"
+
+#ifndef _PATH_VARRUN
+#define    _PATH_VARRUN    "/var/run/"
+#endif
+
+#define _PATH_INETDPID      _PATH_VARRUN "inetd.pid"
diff --git a/ipfw.tproj/Makefile b/ipfw.tproj/Makefile
new file mode 100644 (file)
index 0000000..7114d40
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the Apple Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ipfw
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ipfw.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble ipfw.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ipfw.tproj/Makefile.postamble b/ipfw.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..ef51853
--- /dev/null
@@ -0,0 +1,104 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+
+install-man-page:
+       install -d $(DSTROOT)/usr/share/man/man8
+       install -c -m 444 ipfw.8 $(DSTROOT)/usr/share/man/man8/ipfw.8
diff --git a/ipfw.tproj/Makefile.preamble b/ipfw.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..a4606c6
--- /dev/null
@@ -0,0 +1,140 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+DSTROOT = $(HOME)
+
+AFTER_INSTALL += install-man-page
+
diff --git a/ipfw.tproj/PB.project b/ipfw.tproj/PB.project
new file mode 100644 (file)
index 0000000..ab3c121
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        OTHER_LINKED = (ipfw.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, ipfw.8); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_INSTALLDIR = /bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ipfw; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = /Library/Executables; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ipfw.tproj/ipfw.8 b/ipfw.tproj/ipfw.8
new file mode 100644 (file)
index 0000000..26a7980
--- /dev/null
@@ -0,0 +1,733 @@
+.\"
+.\" $Id: ipfw.8,v 1.1.1.1 2000/01/11 01:48:49 wsanchez Exp $
+.\"
+.Dd July 20, 1996
+.Dt IPFW 8 SMM
+.Os FreeBSD
+.Sh NAME
+.Nm ipfw
+.Nd controlling utility for IP firewall
+.Sh SYNOPSIS
+.Nm ipfw
+.Op Fl q
+.Oo
+.Fl p Ar preproc
+.Op Fl D Ar macro Ns Op Ns =value
+.Op Fl U Ar macro
+.Oc
+file
+.Nm ipfw
+.Oo
+.Fl f
+|
+.Fl q
+.Oc
+flush
+.Nm ipfw
+.Oo
+.Fl q
+.Oc
+zero
+.Op Ar number ...
+.Nm ipfw
+delete
+.Ar number ...
+.Nm ipfw
+.Op Fl aftN
+list
+.Op Ar number ...
+.Nm ipfw
+.Oo
+.Fl ftN
+.Oc
+show
+.Op Ar number ...
+.Nm ipfw
+.Oo
+.Fl q
+.Oc
+add
+.Op Ar number
+.Ar action 
+.Op log
+.Ar proto
+from
+.Ar src
+to
+.Ar dst
+.Op via Ar name | ipno
+.Op Ar options
+.Sh DESCRIPTION
+If used as shown in the first synopsis line, the
+.Ar file
+will be read line by line and applied as arguments to the 
+.Nm
+command.
+.Pp
+Optionally, a preprocessor can be specified using
+.Fl p Ar preproc
+where
+.Ar file
+is to be piped through.  Useful preprocessors include
+.Xr cpp 1
+and
+.Xr m4 1 .
+If
+.Ar preproc
+doesn't start with a slash as its first character, the usual
+.Ev PATH
+name search is performed.  Care should be taken with this in environments
+where not all filesystems are mounted (yet) by the time
+.Nm
+is being run (e. g. since they are mounted over NFS).  Once
+.Fl p
+has been specified, optional
+.Fl D
+and
+.Fl U
+specifications can follow and will be passed on to the preprocessor.
+This allows for flexible configuration files (like conditionalizing
+them on the local hostname) and the use of macros to centralize
+frequently required arguments like IP addresses.
+.Pp
+Each packet that has been received or is about to be sent goes through
+the
+.Nm
+rules. In the case of a host acting as a gateway, packets that are
+forwarded by the host are processed by
+.Nm
+twice
+.Po
+once when entering, and once when leaving
+.Pc .
+Each packet can be filtered based on the following information that is
+associated with it:
+.Pp
+.Bl -tag -offset indent -compact -width xxxx
+.It Receive Interface Pq Ar recv
+Interface over which the packet was received
+.It Transmit Interface Pq Ar xmit
+Interface over which the packet would be transmitted
+.It Incoming Pq Ar in
+Packet was just received
+.It Outgoing Pq Ar out
+Packet would be transmitted
+.It Source IP Address
+Sender's IP Address
+.It Destination IP Address
+Target's IP Address
+.It Protocol
+IP protocol, including but not limited to IP
+.Pq Ar ip ,
+UDP
+.Pq Ar udp ,
+TCP
+.Pq Ar tcp ,
+or
+ICMP
+.Pq Ar icmp
+.It Source Port
+Sender's UDP or TCP port
+.It Destination Port
+Target's UDP or TCP port
+.It Connection Setup Flag Pq Ar setup
+This packet is a request to setup a TCP connection
+.It Connection Established Flag Pq Ar established
+This packet is part of an established TCP connection
+.It All TCP Flags Pq Ar tcpflags
+One or more of the TCP flags: close connection
+.Pq Ar fin ,
+open connection
+.Pq Ar syn ,
+reset connection
+.Pq Ar rst ,
+push
+.Pq Ar psh ,
+acknowledgment
+.Pq Ar ack ,
+and
+urgent
+.Pq Ar urg
+.It Fragment Flag Pq Ar frag
+This packet is a fragment of an IP packet
+.It IP Options Pq Ar ipoptions
+One or more of the IP options: strict source route
+.Pq Ar ssrr ,
+loose source route
+.Pq Ar lsrr ,
+record route
+.Pq Ar rr ,
+and timestamp
+.Pq Ar ts
+.It ICMP Types Pq Ar icmptypes
+One or more of the ICMP types: echo reply
+.Pq Ar 0 ,
+destination unreachable
+.Pq Ar 3 ,
+source quench
+.Pq Ar 4 ,
+redirect
+.Pq Ar 5 ,
+echo request
+.Pq Ar 8 ,
+router advertisement
+.Pq Ar 9 ,
+router solicitation
+.Pq Ar 10 ,
+time-to-live exceeded
+.Pq Ar 11 ,
+IP header bad
+.Pq Ar 12 ,
+timestamp request
+.Pq Ar 13 ,
+timestamp reply
+.Pq Ar 14 ,
+information request
+.Pq Ar 15 ,
+information reply
+.Pq Ar 16 ,
+address mask request
+.Pq Ar 17 ,
+and address mask reply
+.Pq Ar 18
+.El
+.Pp
+Note that may be dangerous to filter on the source IP address or
+source TCP/UDP port because either or both could easily be spoofed.
+.Pp
+The
+.Nm
+code works by going through the rule-list for each packet
+until a match is found.
+All rules have two associated counters, a packet count and
+a byte count.
+These counters are updated when a packet matches the rule.
+.Pp
+The rules are ordered by a 
+.Dq line-number
+from 1 to 65534 that is used
+to order and delete rules. Rules are tried in increasing order, and the
+first rule that matches a packet applies.
+Multiple rules may share the same number and apply in
+the order in which they were added.
+.Pp
+If a rule is added without a number, it is numbered 100 higher than the highest
+defined rule number, unless the highest defined rule number is 65435 or
+greater, in which case new rules are given that same number.
+.Pp
+The delete operation deletes the first rule with number
+.Ar number ,
+if any.
+.Pp
+The list command prints out the current rule set.
+.Pp
+The show command is equivalent to 
+.Sq ipfw -a list .
+.Pp
+The zero operation zeroes the counters associated with rule number
+.Ar number .
+.Pp
+The flush operation removes all rules.
+.Pp
+Any command beginning with a 
+.Sq # ,
+or being all blank, is ignored.
+.Pp
+One rule is always present:
+.Bd -literal -offset center
+65535 deny all from any to any
+.Ed
+.Pp
+This rule is the default policy, i.e., don't allow anything at all.
+Your job in setting up rules is to modify this policy to match your
+needs.
+.Pp
+However, if the kernel option
+.Dq IPFIREWALL_DEFAULT_TO_ACCEPT
+is active, the rule is instead:
+.Bd -literal -offset center
+65535 allow all from any to any
+.Ed
+.Pp
+This variation lets everything pass through.  This option should only be
+activated in particular circumstances, such as if you use the firewall
+system as an on-demand denial-of-service filter that is normally wide open.
+.Pp
+The following options are available:
+.Bl -tag -width flag
+.It Fl a
+While listing, show counter values.  See also 
+.Dq show
+command.
+.It Fl f
+Don't ask for confirmation for commands that can cause problems if misused
+(i.e. flush).
+.Ar Note ,
+if there is no tty associated with the process, this is implied.
+.It Fl q
+While adding, zeroing or flushing, be quiet about actions (implies '-f'). 
+This is useful for adjusting rules by executing multiple
+.Nm
+commands in a script
+.Po
+e.g.,
+.Sq sh /etc/rc.firewall
+.Pc ,
+or by processing a file of many
+.Nm 
+rules,
+across a remote login session.  If a flush is performed in normal
+(verbose) mode (with the default kernel configuration), it prints a message.
+Because all rules are flushed, the
+message cannot be delivered to the login session.  This causes the
+remote login session to be closed and the remainder of the ruleset is
+not processed.  Access to the console is required to recover.
+.It Fl t
+While listing, show last match timestamp.
+.It Fl N
+Try to resolve addresses and service names in output.
+.El
+.Pp
+.Ar action :
+.Bl -hang -offset flag -width 1234567890123456
+.It Ar allow
+Allow packets that match rule.
+The search terminates. Aliases are
+.Ar pass ,
+.Ar permit ,
+and
+.Ar accept .
+.It Ar deny
+Discard packets that match this rule.
+The search terminates.
+.Ar Drop
+is an alias for
+.Ar deny .
+.It Ar reject
+(Deprecated.) Discard packets that match this rule, and try to send an ICMP
+host unreachable notice.
+The search terminates.
+.It Ar unreach code
+Discard packets that match this rule, and try to send an ICMP
+unreachable notice with code
+.Ar code ,
+where
+.Ar code
+is a number from zero to 255, or one of these aliases:
+.Ar net ,
+.Ar host ,
+.Ar protocol ,
+.Ar port ,
+.Ar needfrag ,
+.Ar srcfail ,
+.Ar net-unknown ,
+.Ar host-unknown ,
+.Ar isolated ,
+.Ar net-prohib ,
+.Ar host-prohib ,
+.Ar tosnet ,
+.Ar toshost ,
+.Ar filter-prohib ,
+.Ar host-precedence ,
+or
+.Ar precedence-cutoff .
+The search terminates.
+.It Ar reset
+TCP packets only. Discard packets that match this rule,
+and try to send a TCP reset
+.Pq RST
+notice.
+The search terminates.
+.It Ar count
+Update counters for all packets that match rule.
+The search continues with the next rule.
+.It Ar divert port
+Divert packets that match this rule to the
+.Xr divert 4
+socket bound to port
+.Ar port .
+The search terminates.
+.It Ar tee port
+Send a copy of packets matching this rule to the
+.Xr divert 4
+socket bound to port
+.Ar port .
+The search continues with the next rule. This feature is not yet implemeted.
+.It Ar fwd ipaddr Op ,port
+Change the next-hop on matching packets to
+.Ar ipaddr ,
+which can be an IP address in dotted quad or a host name.
+If
+.Ar ipaddr
+is not a directly-reachable address, the route 
+as found in the local routing table for that IP is used
+instead.
+If
+.Ar ipaddr
+is a local address, then on a packet entering the system from a remote
+host it will be diverted to
+.Ar port
+on the local machine, keeping the local address of the socket set
+to the original IP address the packet was destined for. This is intended
+for use with transparent proxy servers. If the IP is not
+a local address then the port number (if specified) is ignored and
+the rule only applies to packets leaving the system. This will
+also map addresses to local ports when packets are generated locally.
+The search terminates if this rule matches. If the port number is not 
+given then the port number in the packet is used, so that a packet for
+an external machine port Y would be forwarded to local port Y. The kernel
+must have been compiled with optiions IPFIREWALL_FORWARD.
+.It Ar skipto number
+Skip all subsequent rules numbered less than
+.Ar number .
+The search continues with the first rule numbered
+.Ar number
+or higher.
+.El
+.Pp
+If a packet matches more than one
+.Ar divert
+and/or
+.Ar tee
+rule, all but the last are ignored.
+.Pp
+If the kernel was compiled with
+.Dv IPFIREWALL_VERBOSE ,
+then when a packet matches a rule with the
+.Ar log
+keyword a message will be printed on the console.
+If the kernel was compiled with the
+.Dv IPFIREWALL_VERBOSE_LIMIT
+option, then logging will cease after the number of packets
+specified by the option are received for that particular
+chain entry.  Logging may then be re-enabled by clearing
+the packet counter for that entry.
+.Pp
+Console logging and the log limit are adjustable dynamically
+through the
+.Xr sysctl 8
+interface.
+.Pp
+.Ar proto :
+.Bl -hang -offset flag -width 1234567890123456
+.It Ar ip
+All packets match. The alias
+.Ar all
+has the same effect.
+.It Ar tcp
+Only TCP packets match.
+.It Ar udp
+Only UDP packets match.
+.It Ar icmp
+Only ICMP packets match.
+.It Ar <number|name>
+Only packets for the specified protocol matches (see
+.Pa /etc/protocols
+for a complete list).
+.El
+.Pp
+.Ar src 
+and
+.Ar dst :
+.Bl -hang -offset flag
+.It Ar <address/mask>
+.Op Ar ports
+.El
+.Pp
+The
+.Em <address/mask>
+may be specified as:
+.Bl -hang -offset flag -width 1234567890123456
+.It Ar ipno
+An ipnumber of the form 1.2.3.4.
+Only this exact ip number match the rule.
+.It Ar ipno/bits
+An ipnumber with a mask width of the form 1.2.3.4/24.
+In this case all ip numbers from 1.2.3.0 to 1.2.3.255 will match.
+.It Ar ipno:mask
+An ipnumber with a mask width of the form 1.2.3.4:255.255.240.0.
+In this case all ip numbers from 1.2.0.0 to 1.2.15.255 will match.
+.El
+.Pp
+The sense of the match can be inverted by preceding an address with the
+.Dq not
+modifier, causing all other addresses to be matched instead. This
+does not affect the selection of port numbers.
+.Pp
+With the TCP and UDP protocols, optional
+.Em ports
+may be specified as:
+.Pp
+.Bl -hang -offset flag
+.It Ns {port|port-port} Ns Op ,port Ns Op ,...
+.El
+.Pp
+Service names (from 
+.Pa /etc/services )
+may be used instead of numeric port values.
+A range may only be specified as the first value,
+and the length of the port list is limited to
+.Dv IP_FW_MAX_PORTS
+(as defined in 
+.Pa /usr/src/sys/netinet/ip_fw.h )
+ports.
+.Pp
+Fragmented packets which have a non-zero offset (i.e. not the first
+fragment) will never match a rule which has one or more port
+specifications.  See the
+.Ar frag
+option for details on matching fragmented packets.
+.Pp
+Rules can apply to packets when they are incoming, or outgoing, or both.
+The
+.Ar in
+keyword indicates the rule should only match incoming packets.
+The
+.Ar out
+keyword indicates the rule should only match outgoing packets.
+.Pp
+To match packets going through a certain interface, specify
+the interface using
+.Ar via :
+.Bl -hang -offset flag -width 1234567890123456
+.It Ar via ifX
+Packet must be going through interface
+.Ar ifX.
+.It Ar via if*
+Packet must be going through interface
+.Ar ifX ,
+where X is any unit number.
+.It Ar via any
+Packet must be going through
+.Em some
+interface.
+.It Ar via ipno
+Packet must be going through the interface having IP address
+.Ar ipno .
+.El
+.Pp
+The
+.Ar via
+keyword causes the interface to always be checked.
+If
+.Ar recv
+or
+.Ar xmit
+is used instead of
+.Ar via ,
+then the only receive or transmit interface (respectively) is checked.
+By specifying both, it is possible to match packets based on both receive
+and transmit interface, e.g.:
+.Pp
+.Dl "ipfw add 100 deny ip from any to any out recv ed0 xmit ed1"
+.Pp
+The
+.Ar recv
+interface can be tested on either incoming or outgoing packets, while the
+.Ar xmit
+interface can only be tested on outgoing packets. So
+.Ar out
+is required (and
+.Ar in
+invalid) whenver
+.Ar xmit
+is used. Specifying
+.Ar via
+together with
+.Ar xmit
+or
+.Ar recv
+is invalid.
+.Pp
+A packet may not have a receive or transmit interface: packets originating
+from the local host have no receive interface. while packets destined for
+the local host have no transmit interface.
+.Pp
+Additional
+.Ar options :
+.Bl -hang -offset flag -width 1234567890123456
+.It frag
+Matches if the packet is a fragment and this is not the first fragment
+of the datagram.
+.Ar frag
+may not be used in conjunction with either
+.Ar tcpflags
+or TCP/UDP port specifications.
+.It in
+Matches if this packet was on the way in.
+.It out
+Matches if this packet was on the way out.
+.It ipoptions Ar spec
+Matches if the IP header contains the comma separated list of 
+options specified in
+.Ar spec .
+The supported IP options are:
+.Ar ssrr 
+(strict source route),
+.Ar lsrr 
+(loose source route),
+.Ar rr 
+(record packet route), and
+.Ar ts 
+(timestamp).
+The absence of a particular option may be denoted
+with a
+.Dq ! .
+.It established
+Matches packets that have the RST or ACK bits set.
+TCP packets only.
+.It setup
+Matches packets that have the SYN bit set but no ACK bit.
+TCP packets only.
+.It tcpflags Ar spec
+Matches if the TCP header contains the comma separated list of
+flags specified in
+.Ar spec .
+The supported TCP flags are:
+.Ar fin ,
+.Ar syn ,
+.Ar rst ,
+.Ar psh ,
+.Ar ack ,
+and
+.Ar urg .
+The absence of a particular flag may be denoted
+with a
+.Dq ! .
+A rule which contains a
+.Ar tcpflags
+specification can never match a fragmented packet which has
+a non-zero offset.  See the
+.Ar frag
+option for details on matching fragmented packets.
+.It icmptypes Ar types
+Matches if the ICMP type is in the list
+.Ar types .
+The list may be specified as any combination of ranges
+or individual types separated by commas.
+.El
+.Sh CHECKLIST
+Here are some important points to consider when designing your
+rules:
+.Bl -bullet -hang -offset flag 
+.It 
+Remember that you filter both packets going in and out.
+Most connections need packets going in both directions.
+.It
+Remember to test very carefully.
+It is a good idea to be near the console when doing this.
+.It
+Don't forget the loopback interface.
+.El
+.Sh FINE POINTS
+There is one kind of packet that the firewall will always discard,
+that is an IP fragment with a fragment offset of one.
+This is a valid packet, but it only has one use, to try to circumvent
+firewalls.
+.Pp
+If you are logged in over a network, loading the KLD version of
+.Nm
+is probably not as straightforward as you would think.
+I recommend this command line:
+.Bd -literal -offset center
+kldload /modules/ipfw.ko && \e
+ipfw add 32000 allow all from any to any
+.Ed
+.Pp
+Along the same lines, doing an
+.Bd -literal -offset center
+ipfw flush
+.Ed
+.Pp
+in similar surroundings is also a bad idea.
+.Pp
+The IP filter list may not be modified if the system security level
+is set to 3 or higher
+.Po
+see
+.Xr init 8
+for information on system security levels
+.Pc .
+.Sh PACKET DIVERSION
+A divert socket bound to the specified port will receive all packets diverted
+to that port; see
+.Xr divert 4 .
+If no socket is bound to the destination port, or if the kernel
+wasn't compiled with divert socket support, diverted packets are dropped.
+.Sh EXAMPLES
+This command adds an entry which denies all tcp packets from
+.Em cracker.evil.org
+to the telnet port of
+.Em wolf.tambov.su
+from being forwarded by the host:
+.Pp
+.Dl ipfw add deny tcp from cracker.evil.org to wolf.tambov.su 23
+.Pp 
+This one disallows any connection from the entire crackers network to
+my host:
+.Pp
+.Dl ipfw add deny all from 123.45.67.0/24 to my.host.org
+.Pp
+Here is a good usage of the
+.Ar list
+command to see accounting records
+and timestamp information:
+.Pp
+.Dl ipfw -at l
+.Pp
+or in short form without timestamps:
+.Pp
+.Dl ipfw -a l
+.Pp
+This rule diverts all incoming packets from 192.168.2.0/24 to divert port 5000:
+.Pp
+.Dl ipfw divert 5000 all from 192.168.2.0/24 to any in
+.Sh SEE ALSO
+.Xr cpp 1 ,
+.Xr m4 1 ,
+.Xr divert 4 ,
+.Xr ip 4 ,
+.Xr ipfirewall 4 ,
+.Xr protocols 5 ,
+.Xr services 5 ,
+.Xr init 8 ,
+.Xr kldload 8 ,
+.Xr reboot 8 ,
+.Xr sysctl 8 ,
+.Xr syslogd 8 .
+.Sh BUGS
+.Pp
+.Em WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!
+.Pp
+This program can put your computer in rather unusable state. When
+using it for the first time, work on the console of the computer, and
+do
+.Em NOT
+do anything you don't understand.
+.Pp
+When manipulating/adding chain entries, service and protocol names are
+not accepted.
+.Pp
+Incoming packet fragments diverted by
+.Ar divert
+are reassembled before delivery to the socket, whereas fragments diverted via
+.Ar tee
+are not.
+.Pp
+Port aliases containing dashes cannot be first in a list.
+.Pp
+The
+.Dq tee
+action is unimplemented.
+.Sh AUTHORS
+.An Ugen J. S. Antsilevich ,
+.An Poul-Henning Kamp ,
+.An Alex Nash ,
+.An Archie Cobbs .
+API based upon code written by
+.An Daniel Boulet
+for BSDI.
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 2.0 .
diff --git a/ipfw.tproj/ipfw.c b/ipfw.tproj/ipfw.c
new file mode 100644 (file)
index 0000000..7992ec4
--- /dev/null
@@ -0,0 +1,1613 @@
+/*
+ * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
+ * Copyright (c) 1994 Ugen J.S.Antsilevich
+ *
+ * Idea and grammar partially left from:
+ * Copyright (c) 1993 Daniel Boulet
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ *
+ * NEW command line interface for IP firewall facility
+ *
+ * $Id: ipfw.c,v 1.2 2000/06/07 04:22:47 lindak Exp $
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_fw.h>
+#include <net/route.h> /* def. of struct route */
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <netinet/ip_dummynet.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+int            lineno = -1;
+
+int            s;                              /* main RAW socket         */
+int            do_resolv=0;                    /* Would try to resolve all */
+int            do_acct=0;                      /* Show packet/byte count  */
+int            do_time=0;                      /* Show time stamps        */
+int            do_quiet=0;                     /* Be quiet in add and flush  */
+int            do_force=0;                     /* Don't ask for confirmation */
+int            do_pipe=0;                      /* this cmd refers to a pipe */
+
+struct icmpcode {
+       int     code;
+       char    *str;
+};
+
+static struct icmpcode icmpcodes[] = {
+      { ICMP_UNREACH_NET,              "net" },
+      { ICMP_UNREACH_HOST,             "host" },
+      { ICMP_UNREACH_PROTOCOL,         "protocol" },
+      { ICMP_UNREACH_PORT,             "port" },
+      { ICMP_UNREACH_NEEDFRAG,         "needfrag" },
+      { ICMP_UNREACH_SRCFAIL,          "srcfail" },
+      { ICMP_UNREACH_NET_UNKNOWN,      "net-unknown" },
+      { ICMP_UNREACH_HOST_UNKNOWN,     "host-unknown" },
+      { ICMP_UNREACH_ISOLATED,         "isolated" },
+      { ICMP_UNREACH_NET_PROHIB,       "net-prohib" },
+      { ICMP_UNREACH_HOST_PROHIB,      "host-prohib" },
+      { ICMP_UNREACH_TOSNET,           "tosnet" },
+      { ICMP_UNREACH_TOSHOST,          "toshost" },
+      { ICMP_UNREACH_FILTER_PROHIB,    "filter-prohib" },
+      { ICMP_UNREACH_HOST_PRECEDENCE,  "host-precedence" },
+      { ICMP_UNREACH_PRECEDENCE_CUTOFF,        "precedence-cutoff" },
+      { 0, NULL }
+};
+
+static void show_usage(const char *fmt, ...);
+
+static int
+mask_bits(struct in_addr m_ad)
+{
+       int h_fnd=0,h_num=0,i;
+       u_long mask;
+
+       mask=ntohl(m_ad.s_addr);
+       for (i=0;i<sizeof(u_long)*CHAR_BIT;i++) {
+               if (mask & 1L) {
+                       h_fnd=1;
+                       h_num++;
+               } else {
+                       if (h_fnd)
+                               return -1;
+               }
+               mask=mask>>1;
+       }
+       return h_num;
+}                         
+
+static void
+print_port(prot, port, comma)
+       u_char  prot;
+       u_short port;
+       const char *comma;
+{
+       struct servent *se;
+       struct protoent *pe;
+       const char *protocol;
+       int printed = 0;
+
+       if (do_resolv) {
+               pe = getprotobynumber(prot);
+               if (pe)
+                       protocol = pe->p_name;
+               else
+                       protocol = NULL;
+
+               se = getservbyport(htons(port), protocol);
+               if (se) {
+                       printf("%s%s", comma, se->s_name);
+                       printed = 1;
+               }
+       } 
+       if (!printed)
+               printf("%s%d",comma,port);
+}
+
+static void
+print_iface(char *key, union ip_fw_if *un, int byname)
+{
+       char ifnb[FW_IFNLEN+1];
+
+       if (byname) {
+               strncpy(ifnb, un->fu_via_if.name, FW_IFNLEN);
+               ifnb[FW_IFNLEN]='\0';
+               if (un->fu_via_if.unit == -1)
+                       printf(" %s %s*", key, ifnb);
+               else 
+                       printf(" %s %s%d", key, ifnb, un->fu_via_if.unit);
+       } else if (un->fu_via_ip.s_addr != 0) {
+               printf(" %s %s", key, inet_ntoa(un->fu_via_ip));
+       } else
+               printf(" %s any", key);
+}
+
+static void
+print_reject_code(int code)
+{
+       struct icmpcode *ic;
+
+       for (ic = icmpcodes; ic->str; ic++)
+               if (ic->code == code) {
+                       printf("%s", ic->str);
+                       return;
+               }
+       printf("%u", code);
+}
+
+static void
+show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth)
+{
+       char *comma;
+       u_long adrt;
+       struct hostent *he;
+       struct protoent *pe;
+       int i, mb;
+       int nsp = IP_FW_GETNSRCP(chain);
+       int ndp = IP_FW_GETNDSTP(chain);
+
+       if (do_resolv)
+               setservent(1/*stayopen*/);
+
+       printf("%05u ", chain->fw_number);
+
+       if (do_acct) 
+               printf("%*qu %*qu ",pcwidth,chain->fw_pcnt,bcwidth,chain->fw_bcnt);
+
+       if (do_time)
+       {
+               if (chain->timestamp)
+               {
+                       char timestr[30];
+
+                       strcpy(timestr, ctime((time_t *)&chain->timestamp));
+                       *strchr(timestr, '\n') = '\0';
+                       printf("%s ", timestr);
+               }
+               else
+                       printf("                         ");
+       }
+
+       switch (chain->fw_flg & IP_FW_F_COMMAND)
+       {
+               case IP_FW_F_ACCEPT:
+                       printf("allow");
+                       break;
+               case IP_FW_F_DENY:
+                       printf("deny");
+                       break;
+               case IP_FW_F_COUNT:
+                       printf("count");
+                       break;
+               case IP_FW_F_DIVERT:
+                       printf("divert %u", chain->fw_divert_port);
+                       break;
+               case IP_FW_F_TEE:
+                       printf("tee %u", chain->fw_divert_port);
+                       break;
+               case IP_FW_F_SKIPTO:
+                       printf("skipto %u", chain->fw_skipto_rule);
+                       break;
+                case IP_FW_F_PIPE:
+                        printf("pipe %u", chain->fw_skipto_rule);
+                        break ;
+               case IP_FW_F_REJECT:
+                       if (chain->fw_reject_code == IP_FW_REJECT_RST)
+                               printf("reset");
+                       else {
+                               printf("unreach ");
+                               print_reject_code(chain->fw_reject_code);
+                       }
+                       break;
+               case IP_FW_F_FWD:
+                       printf("fwd %s", inet_ntoa(chain->fw_fwd_ip.sin_addr));
+                       if(chain->fw_fwd_ip.sin_port)
+                               printf(",%d", chain->fw_fwd_ip.sin_port);
+                       break;
+               default:
+                       errx(EX_OSERR, "impossible");
+       }
+   
+       if (chain->fw_flg & IP_FW_F_PRN)
+               printf(" log");
+
+       pe = getprotobynumber(chain->fw_prot);
+       if (pe)
+               printf(" %s", pe->p_name);
+       else
+               printf(" %u", chain->fw_prot);
+
+       printf(" from %s", chain->fw_flg & IP_FW_F_INVSRC ? "not " : "");
+
+       adrt=ntohl(chain->fw_smsk.s_addr);
+       if (adrt==ULONG_MAX && do_resolv) {
+               adrt=(chain->fw_src.s_addr);
+               he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
+               if (he==NULL) {
+                       printf(inet_ntoa(chain->fw_src));
+               } else
+                       printf("%s",he->h_name);
+       } else {
+               if (adrt!=ULONG_MAX) {
+                       mb=mask_bits(chain->fw_smsk);
+                       if (mb == 0) {
+                               printf("any");
+                       } else {
+                               if (mb > 0) {
+                                       printf(inet_ntoa(chain->fw_src));
+                                       printf("/%d",mb);
+                               } else {
+                                       printf(inet_ntoa(chain->fw_src));
+                                       printf(":");
+                                       printf(inet_ntoa(chain->fw_smsk));
+                               }
+                       }
+               } else
+                       printf(inet_ntoa(chain->fw_src));
+       }
+
+       if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) {
+               comma = " ";
+               for (i = 0; i < nsp; i++) {
+                       print_port(chain->fw_prot, chain->fw_uar.fw_pts[i], comma);
+                       if (i==0 && (chain->fw_flg & IP_FW_F_SRNG))
+                               comma = "-";
+                       else
+                               comma = ",";
+               }
+       }
+
+       printf(" to %s", chain->fw_flg & IP_FW_F_INVDST ? "not " : "");
+
+       adrt=ntohl(chain->fw_dmsk.s_addr);
+       if (adrt==ULONG_MAX && do_resolv) {
+               adrt=(chain->fw_dst.s_addr);
+               he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
+               if (he==NULL) {
+                       printf(inet_ntoa(chain->fw_dst));
+               } else
+                       printf("%s",he->h_name);
+       } else {
+               if (adrt!=ULONG_MAX) {
+                       mb=mask_bits(chain->fw_dmsk);
+                       if (mb == 0) {
+                               printf("any");
+                       } else {
+                               if (mb > 0) {
+                                       printf(inet_ntoa(chain->fw_dst));
+                                       printf("/%d",mb);
+                               } else {
+                                       printf(inet_ntoa(chain->fw_dst));
+                                       printf(":");
+                                       printf(inet_ntoa(chain->fw_dmsk));
+                               }
+                       }
+               } else
+                       printf(inet_ntoa(chain->fw_dst));
+       }
+
+       if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) {
+               comma = " ";
+               for (i = 0; i < ndp; i++) {
+                       print_port(chain->fw_prot, chain->fw_uar.fw_pts[nsp+i], comma);
+                       if (i==0 && (chain->fw_flg & IP_FW_F_DRNG))
+                               comma = "-";
+                       else
+                               comma = ",";
+               }
+       }
+
+       /* Direction */
+       if ((chain->fw_flg & IP_FW_F_IN) && !(chain->fw_flg & IP_FW_F_OUT))
+               printf(" in");
+       if (!(chain->fw_flg & IP_FW_F_IN) && (chain->fw_flg & IP_FW_F_OUT))
+               printf(" out");
+
+       /* Handle hack for "via" backwards compatibility */
+       if ((chain->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
+               print_iface("via",
+                   &chain->fw_in_if, chain->fw_flg & IP_FW_F_IIFNAME);
+       } else {
+               /* Receive interface specified */
+               if (chain->fw_flg & IP_FW_F_IIFACE)
+                       print_iface("recv", &chain->fw_in_if,
+                           chain->fw_flg & IP_FW_F_IIFNAME);
+               /* Transmit interface specified */
+               if (chain->fw_flg & IP_FW_F_OIFACE)
+                       print_iface("xmit", &chain->fw_out_if,
+                           chain->fw_flg & IP_FW_F_OIFNAME);
+       }
+
+       if (chain->fw_flg & IP_FW_F_FRAG)
+               printf(" frag");
+
+       if (chain->fw_ipopt || chain->fw_ipnopt) {
+               int     _opt_printed = 0;
+#define PRINTOPT(x)    {if (_opt_printed) printf(",");\
+                       printf(x); _opt_printed = 1;}
+
+               printf(" ipopt ");
+               if (chain->fw_ipopt  & IP_FW_IPOPT_SSRR) PRINTOPT("ssrr");
+               if (chain->fw_ipnopt & IP_FW_IPOPT_SSRR) PRINTOPT("!ssrr");
+               if (chain->fw_ipopt  & IP_FW_IPOPT_LSRR) PRINTOPT("lsrr");
+               if (chain->fw_ipnopt & IP_FW_IPOPT_LSRR) PRINTOPT("!lsrr");
+               if (chain->fw_ipopt  & IP_FW_IPOPT_RR)   PRINTOPT("rr");
+               if (chain->fw_ipnopt & IP_FW_IPOPT_RR)   PRINTOPT("!rr");
+               if (chain->fw_ipopt  & IP_FW_IPOPT_TS)   PRINTOPT("ts");
+               if (chain->fw_ipnopt & IP_FW_IPOPT_TS)   PRINTOPT("!ts");
+       } 
+
+       if (chain->fw_tcpf & IP_FW_TCPF_ESTAB) 
+               printf(" established");
+       else if (chain->fw_tcpf == IP_FW_TCPF_SYN &&
+           chain->fw_tcpnf == IP_FW_TCPF_ACK)
+               printf(" setup");
+       else if (chain->fw_tcpf || chain->fw_tcpnf) {
+               int     _flg_printed = 0;
+#define PRINTFLG(x)    {if (_flg_printed) printf(",");\
+                       printf(x); _flg_printed = 1;}
+
+               printf(" tcpflg ");
+               if (chain->fw_tcpf  & IP_FW_TCPF_FIN)  PRINTFLG("fin");
+               if (chain->fw_tcpnf & IP_FW_TCPF_FIN)  PRINTFLG("!fin");
+               if (chain->fw_tcpf  & IP_FW_TCPF_SYN)  PRINTFLG("syn");
+               if (chain->fw_tcpnf & IP_FW_TCPF_SYN)  PRINTFLG("!syn");
+               if (chain->fw_tcpf  & IP_FW_TCPF_RST)  PRINTFLG("rst");
+               if (chain->fw_tcpnf & IP_FW_TCPF_RST)  PRINTFLG("!rst");
+               if (chain->fw_tcpf  & IP_FW_TCPF_PSH)  PRINTFLG("psh");
+               if (chain->fw_tcpnf & IP_FW_TCPF_PSH)  PRINTFLG("!psh");
+               if (chain->fw_tcpf  & IP_FW_TCPF_ACK)  PRINTFLG("ack");
+               if (chain->fw_tcpnf & IP_FW_TCPF_ACK)  PRINTFLG("!ack");
+               if (chain->fw_tcpf  & IP_FW_TCPF_URG)  PRINTFLG("urg");
+               if (chain->fw_tcpnf & IP_FW_TCPF_URG)  PRINTFLG("!urg");
+       } 
+       if (chain->fw_flg & IP_FW_F_ICMPBIT) {
+               int type_index;
+               int first = 1;
+
+               printf(" icmptype");
+
+               for (type_index = 0; type_index < IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8; ++type_index)
+                       if (chain->fw_uar.fw_icmptypes[type_index / (sizeof(unsigned) * 8)] & 
+                               (1U << (type_index % (sizeof(unsigned) * 8)))) {
+                               printf("%c%d", first == 1 ? ' ' : ',', type_index);
+                               first = 0;
+                       }
+       }
+       printf("\n");
+       if (do_resolv)
+               endservent();
+}
+
+static void
+list(ac, av)
+       int     ac;
+       char    **av;
+{
+       struct ip_fw *rules;
+       struct dn_pipe *pipes;
+       void *data = NULL;
+       int pcwidth = 0;
+       int bcwidth = 0;
+       int n, num = 0;
+
+       /* get rules or pipes from kernel, resizing array as necessary */
+       {
+               const int unit = do_pipe ? sizeof(*pipes) : sizeof(*rules);
+               const int ocmd = do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
+               int nalloc = 0;
+               int nbytes;
+
+               while (num >= nalloc) {
+                       nalloc = nalloc * 2 + 200;
+                       nbytes = nalloc * unit;
+                       if ((data = realloc(data, nbytes)) == NULL)
+                               err(EX_OSERR, "realloc");
+                       if (getsockopt(s, IPPROTO_IP, ocmd, data, &nbytes) < 0)
+                               err(EX_OSERR, "getsockopt(IP_%s_GET)",
+                                   do_pipe ? "DUMMYNET" : "FW");
+                       num = nbytes / unit;
+               }
+       }
+
+       /* display requested pipes */
+       if (do_pipe) {
+           u_long rulenum;
+
+           pipes = (struct dn_pipe *) data;
+           if (ac > 0)
+               rulenum = strtoul(*av++, NULL, 10);
+           else
+               rulenum = 0 ;
+           for (n = 0; n < num; n++) {
+               struct dn_pipe *const p = &pipes[n];
+               double b = p->bandwidth ;
+               char buf[30] ;
+               char qs[30] ;
+               char plr[30] ;
+               int l ;
+
+               if (rulenum != 0 && rulenum != p->pipe_nr)
+                       continue;
+               if (b == 0)
+                   sprintf(buf, "unlimited");
+               else if (b >= 1000000)
+                   sprintf(buf, "%7.3f Mbit/s", b/1000000 );
+               else if (b >= 1000)
+                   sprintf(buf, "%7.3f Kbit/s", b/1000 );
+               else
+                   sprintf(buf, "%7.3f bit/s ", b );
+
+               if ( (l = p->queue_size_bytes) != 0 ) {
+                   if (l >= 8192)
+                       sprintf(qs,"%d KB", l / 1024);
+                   else
+                       sprintf(qs,"%d B", l);
+               } else
+                   sprintf(qs,"%3d sl.", p->queue_size);
+               if (p->plr)
+                   sprintf(plr,"plr %f", 1.0*p->plr/(double)(0x7fffffff));
+               else
+                   plr[0]='\0';
+
+               printf("%05d: %s %4d ms %s %s -- %d pkts (%d B) %d drops\n",
+                   p->pipe_nr, buf, p->delay, qs, plr,
+                   p->r_len, p->r_len_bytes, p->r_drops);
+           }
+           free(data);
+           return;
+       }
+
+       /* if showing stats, figure out column widths ahead of time */
+       rules = (struct ip_fw *) data;
+       if (do_acct) {
+               for (n = 0; n < num; n++) {
+                       struct ip_fw *const r = &rules[n];
+                       char temp[32];
+                       int width;
+
+                       /* packet counter */
+                       width = sprintf(temp, "%qu", r->fw_pcnt);
+                       if (width > pcwidth)
+                               pcwidth = width;
+
+                       /* byte counter */
+                       width = sprintf(temp, "%qu", r->fw_bcnt);
+                       if (width > bcwidth)
+                               bcwidth = width;
+               }
+       }
+       if (ac == 0) {
+               /* display all rules */
+               for (n = 0; n < num; n++) {
+                       struct ip_fw *const r = &rules[n];
+
+                       show_ipfw(r, pcwidth, bcwidth);
+               }
+       } else {
+               /* display specific rules requested on command line */
+               int exitval = EX_OK;
+
+               while (ac--) {
+                       u_long rnum;
+                       char *endptr;
+                       int seen;
+
+                       /* convert command line rule # */
+                       rnum = strtoul(*av++, &endptr, 10);
+                       if (*endptr) {
+                               exitval = EX_USAGE;
+                               warnx("invalid rule number: %s", *(av - 1));
+                               continue;
+                       }
+                       for (seen = n = 0; n < num; n++) {
+                               struct ip_fw *const r = &rules[n];
+
+                               if (r->fw_number > rnum)
+                                       break;
+                               if (r->fw_number == rnum) {
+                                       show_ipfw(r, pcwidth, bcwidth);
+                                       seen = 1;
+                               }
+                       }
+                       if (!seen) {
+                               /* give precedence to other error(s) */
+                               if (exitval == EX_OK)
+                                       exitval = EX_UNAVAILABLE;
+                               warnx("rule %lu does not exist", rnum);
+                       }
+               }
+               if (exitval != EX_OK)
+                       exit(exitval);
+       }
+       free(data);
+}
+
+static void
+show_usage(const char *fmt, ...)
+{
+       if (fmt) {
+               char buf[100];
+               va_list args;
+
+               va_start(args, fmt);
+               vsnprintf(buf, sizeof(buf), fmt, args);
+               va_end(args);
+               warnx("error: %s", buf);
+       }
+       fprintf(stderr, "usage: ipfw [options]\n"
+"    flush\n"
+"    add [number] rule\n"
+"    delete number ...\n"
+"    list [number ...]\n"
+"    show [number ...]\n"
+"    zero [number ...]\n"
+"  rule:  action proto src dst extras...\n"
+"    action:\n"
+"      {allow|permit|accept|pass|deny|drop|reject|unreach code|\n"
+"       reset|count|skipto num|divert port|tee port|fwd ip} [log]\n"
+"    proto: {ip|tcp|udp|icmp|<number>}\n"
+"    src: from [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
+"    dst: to [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
+"  extras:\n"
+"    fragment     (may not be used with ports or tcpflags)\n"
+"    in\n"
+"    out\n"
+"    {xmit|recv|via} {iface|ip|any}\n"
+"    {established|setup}\n"
+"    tcpflags [!]{syn|fin|rst|ack|psh|urg},...\n"
+"    ipoptions [!]{ssrr|lsrr|rr|ts},...\n"
+"    icmptypes {type[,type]}...\n");
+
+       exit(EX_USAGE);
+}
+
+static int
+lookup_host (host, ipaddr)
+       char *host;
+       struct in_addr *ipaddr;
+{
+       struct hostent *he = gethostbyname(host);
+
+    if (!he) {
+        if (inet_aton(host, ipaddr))
+            return(0);
+        else
+            return(-1);
+    }
+       *ipaddr = *(struct in_addr *)he->h_addr_list[0];
+
+       return(0);
+}
+
+static void
+fill_ip(ipno, mask, acp, avp)
+       struct in_addr *ipno, *mask;
+       int *acp;
+       char ***avp;
+{
+       int ac = *acp;
+       char **av = *avp;
+       char *p = 0, md = 0;
+
+       if (ac && !strncmp(*av,"any",strlen(*av))) {
+               ipno->s_addr = mask->s_addr = 0; av++; ac--;
+       } else {
+               p = strchr(*av, '/');
+               if (!p) 
+                       p = strchr(*av, ':');
+               if (p) {
+                       md = *p;
+                       *p++ = '\0'; 
+               }
+
+               if (lookup_host(*av, ipno) != 0)
+                       show_usage("hostname ``%s'' unknown", *av);
+               switch (md) {
+                       case ':':
+                               if (!inet_aton(p,mask))
+                                       show_usage("bad netmask ``%s''", p);
+                               break;
+                       case '/':
+                               if (atoi(p) == 0) {
+                                       mask->s_addr = 0;
+                               } else if (atoi(p) > 32) {
+                                       show_usage("bad width ``%s''", p);
+                               } else {
+                                       mask->s_addr =
+                                           htonl(~0 << (32 - atoi(p)));
+                               }
+                               break;
+                       default:
+                               mask->s_addr = htonl(~0);
+                               break;
+               }
+               ipno->s_addr &= mask->s_addr;
+               av++;
+               ac--;
+       }
+       *acp = ac;
+       *avp = av;
+}
+
+static void
+fill_reject_code(u_short *codep, char *str)
+{
+       struct icmpcode *ic;
+       u_long val;
+       char *s;
+
+       val = strtoul(str, &s, 0);
+       if (s != str && *s == '\0' && val < 0x100) {
+               *codep = val;
+               return;
+       }
+       for (ic = icmpcodes; ic->str; ic++)
+               if (!strcasecmp(str, ic->str)) {
+                       *codep = ic->code;
+                       return;
+               }
+       show_usage("unknown ICMP unreachable code ``%s''", str);
+}
+
+static void
+add_port(cnt, ptr, off, port)
+       u_short *cnt, *ptr, off, port;
+{
+       if (off + *cnt >= IP_FW_MAX_PORTS)
+               errx(EX_USAGE, "too many ports (max is %d)", IP_FW_MAX_PORTS);
+       ptr[off+*cnt] = port;
+       (*cnt)++;
+}
+
+static int
+lookup_port(const char *arg, int test, int nodash)
+{
+       int             val;
+       char            *earg, buf[32];
+       struct servent  *s;
+
+       snprintf(buf, sizeof(buf), "%s", arg);
+       buf[strcspn(arg, nodash ? "-," : ",")] = 0;
+       val = (int) strtoul(buf, &earg, 0);
+       if (!*buf || *earg) {
+               setservent(1);
+               if ((s = getservbyname(buf, NULL))) {
+                       val = htons(s->s_port);
+               } else {
+                       if (!test) {
+                               errx(EX_DATAERR, "unknown port ``%s''", arg);
+                       }
+                       val = -1;
+               }
+       } else {
+               if (val < 0 || val > 0xffff) {
+                       if (!test) {
+                               errx(EX_DATAERR, "port ``%s'' out of range", arg);
+                       }
+                       val = -1;
+               }
+       }
+       return(val);
+}
+
+static int
+fill_port(cnt, ptr, off, arg)
+       u_short *cnt, *ptr, off;
+       char *arg;
+{
+       char *s;
+       int initial_range = 0;
+
+       s = arg + strcspn(arg, "-,");   /* first port name can't have a dash */
+       if (*s == '-') {
+               *s++ = '\0';
+               if (strchr(arg, ','))
+                       errx(EX_USAGE, "port range must be first in list");
+               add_port(cnt, ptr, off, *arg ? lookup_port(arg, 0, 0) : 0x0000);
+               arg = s;
+               s = strchr(arg,',');
+               if (s)
+                       *s++ = '\0';
+               add_port(cnt, ptr, off, *arg ? lookup_port(arg, 0, 0) : 0xffff);
+               arg = s;
+               initial_range = 1;
+       }
+       while (arg != NULL) {
+               s = strchr(arg,',');
+               if (s)
+                       *s++ = '\0';
+               add_port(cnt, ptr, off, lookup_port(arg, 0, 0));
+               arg = s;
+       }
+       return initial_range;
+}
+
+static void
+fill_tcpflag(set, reset, vp)
+       u_char *set, *reset;
+       char **vp;
+{
+       char *p = *vp,*q;
+       u_char *d;
+
+       while (p && *p) {
+               struct tpcflags {
+                       char * name;
+                       u_char value;
+               } flags[] = {
+                       { "syn", IP_FW_TCPF_SYN },
+                       { "fin", IP_FW_TCPF_FIN },
+                       { "ack", IP_FW_TCPF_ACK },
+                       { "psh", IP_FW_TCPF_PSH },
+                       { "rst", IP_FW_TCPF_RST },
+                       { "urg", IP_FW_TCPF_URG }
+               };
+               int i;
+
+               if (*p == '!') {
+                       p++;
+                       d = reset;
+               } else {
+                       d = set;
+               }
+               q = strchr(p, ',');
+               if (q) 
+                       *q++ = '\0';
+               for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i)
+                       if (!strncmp(p, flags[i].name, strlen(p))) {
+                               *d |= flags[i].value;
+                               break;
+                       }
+               if (i == sizeof(flags) / sizeof(flags[0]))
+                       show_usage("invalid tcp flag ``%s''", p);
+               p = q;
+       }
+}
+
+static void
+fill_ipopt(u_char *set, u_char *reset, char **vp)
+{
+       char *p = *vp,*q;
+       u_char *d;
+
+       while (p && *p) {
+               if (*p == '!') {
+                       p++;
+                       d = reset;
+               } else {
+                       d = set;
+               }
+               q = strchr(p, ',');
+               if (q) 
+                       *q++ = '\0';
+               if (!strncmp(p,"ssrr",strlen(p))) *d |= IP_FW_IPOPT_SSRR;
+               if (!strncmp(p,"lsrr",strlen(p))) *d |= IP_FW_IPOPT_LSRR;
+               if (!strncmp(p,"rr",strlen(p)))   *d |= IP_FW_IPOPT_RR;
+               if (!strncmp(p,"ts",strlen(p)))   *d |= IP_FW_IPOPT_TS;
+               p = q;
+       }
+}
+
+static void
+fill_icmptypes(types, vp, fw_flg)
+       u_long *types;
+       char **vp;
+       u_int *fw_flg;
+{
+       char *c = *vp;
+
+       while (*c)
+       {
+               unsigned long icmptype;
+
+               if ( *c == ',' )
+                       ++c;
+
+               icmptype = strtoul(c, &c, 0);
+
+               if ( *c != ',' && *c != '\0' )
+                       show_usage("invalid ICMP type");
+
+               if (icmptype >= IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8)
+                       show_usage("ICMP type out of range");
+
+               types[icmptype / (sizeof(unsigned) * 8)] |= 
+                       1 << (icmptype % (sizeof(unsigned) * 8));
+               *fw_flg |= IP_FW_F_ICMPBIT;
+       }
+}
+
+static void
+delete(ac,av)
+       int ac;
+       char **av;
+{
+       struct ip_fw rule;
+       struct dn_pipe pipe;
+       int i;
+       int exitval = EX_OK;
+
+       memset(&rule, 0, sizeof rule);
+       memset(&pipe, 0, sizeof pipe);
+
+       av++; ac--;
+
+       /* Rule number */
+       while (ac && isdigit(**av)) {
+            if (do_pipe) {
+                pipe.pipe_nr = atoi(*av); av++; ac--;
+                i = setsockopt(s, IPPROTO_IP, IP_DUMMYNET_DEL,
+                    &pipe, sizeof pipe);
+                if (i) {
+                    exitval = 1;
+                    warn("rule %u: setsockopt(%s)", pipe.pipe_nr, "IP_DUMMYNET_DEL");
+                }
+            } else {
+               rule.fw_number = atoi(*av); av++; ac--;
+               i = setsockopt(s, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule);
+               if (i) {
+                       exitval = EX_UNAVAILABLE;
+                       warn("rule %u: setsockopt(%s)", rule.fw_number, "IP_FW_DEL");
+               }
+       }
+       }
+       if (exitval != EX_OK)
+               exit(exitval);
+}
+
+static void
+verify_interface(union ip_fw_if *ifu)
+{
+       struct ifreq ifr;
+
+       /*
+        *      If a unit was specified, check for that exact interface.
+        *      If a wildcard was specified, check for unit 0.
+        */
+       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", 
+                        ifu->fu_via_if.name,
+                        ifu->fu_via_if.unit == -1 ? 0 : ifu->fu_via_if.unit);
+
+       if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
+               warnx("warning: interface ``%s'' does not exist", ifr.ifr_name);
+}
+
+static void
+fill_iface(char *which, union ip_fw_if *ifu, int *byname, int ac, char *arg)
+{
+       if (!ac)
+           show_usage("missing argument for ``%s''", which);
+
+       /* Parse the interface or address */
+       if (!strcmp(arg, "any")) {
+               ifu->fu_via_ip.s_addr = 0;
+               *byname = 0;
+       } else if (!isdigit(*arg)) {
+               char *q;
+
+               *byname = 1;
+               strncpy(ifu->fu_via_if.name, arg, sizeof(ifu->fu_via_if.name));
+               ifu->fu_via_if.name[sizeof(ifu->fu_via_if.name) - 1] = '\0';
+               for (q = ifu->fu_via_if.name;
+                   *q && !isdigit(*q) && *q != '*'; q++)
+                       continue;
+               ifu->fu_via_if.unit = (*q == '*') ? -1 : atoi(q);
+               *q = '\0';
+               verify_interface(ifu);
+       } else if (!inet_aton(arg, &ifu->fu_via_ip)) {
+               show_usage("bad ip address ``%s''", arg);
+       } else
+               *byname = 0;
+}
+
+static void
+config_pipe(int ac, char **av)
+{
+       struct dn_pipe pipe;
+        int i ;
+        char *end ;
+        memset(&pipe, 0, sizeof pipe);
+        av++; ac--;
+        /* Pipe number */
+        if (ac && isdigit(**av)) {
+                pipe.pipe_nr = atoi(*av); av++; ac--;
+        }
+        while (ac > 1) {
+            if (!strncmp(*av,"bw",strlen(*av)) ||
+                ! strncmp(*av,"bandwidth",strlen(*av))) {
+                pipe.bandwidth = strtoul(av[1], &end, 0);
+                if (*end == 'K')
+                        end++, pipe.bandwidth *= 1000 ;
+                else if (*end == 'M')
+                        end++, pipe.bandwidth *= 1000000 ;
+                if (*end == 'B')
+                        pipe.bandwidth *= 8 ;
+                av+=2; ac-=2;
+            } else if (!strncmp(*av,"delay",strlen(*av)) ) {
+                pipe.delay = strtoul(av[1], NULL, 0);
+                av+=2; ac-=2;
+            } else if (!strncmp(*av,"plr",strlen(*av)) ) {
+                
+                double d = strtod(av[1], NULL);
+                pipe.plr = (int)(d*0x7fffffff) ;
+                av+=2; ac-=2;
+            } else if (!strncmp(*av,"queue",strlen(*av)) ) {
+                end = NULL ;
+                pipe.queue_size = strtoul(av[1], &end, 0);
+                if (*end == 'K') {
+                    pipe.queue_size_bytes = pipe.queue_size*1024 ;
+                    pipe.queue_size = 0 ;
+                } else if (*end == 'B') {
+                    pipe.queue_size_bytes = pipe.queue_size ;
+                    pipe.queue_size = 0 ;
+                }
+                av+=2; ac-=2;
+            } else
+                show_usage("unrecognised option ``%s''", *av);
+        }
+        if (pipe.pipe_nr == 0 )
+            show_usage("pipe_nr %d be > 0", pipe.pipe_nr);
+        if (pipe.queue_size > 100 )
+            show_usage("queue size %d must be 2 <= x <= 100", pipe.queue_size);
+        if (pipe.delay > 10000 )
+            show_usage("delay %d must be < 10000", pipe.delay);
+#if 0
+        printf("configuring pipe %d bw %d delay %d size %d\n",
+                pipe.pipe_nr, pipe.bandwidth, pipe.delay, pipe.queue_size);
+#endif
+        i = setsockopt(s,IPPROTO_IP, IP_DUMMYNET_CONFIGURE, &pipe,sizeof pipe);
+        if (i)
+                err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
+                
+}
+
+static void
+add(ac,av)
+       int ac;
+       char **av;
+{
+       struct ip_fw rule;
+       int i;
+       u_char proto;
+       struct protoent *pe;
+       int saw_xmrc = 0, saw_via = 0;
+       
+       memset(&rule, 0, sizeof rule);
+
+       av++; ac--;
+
+       /* Rule number */
+       if (ac && isdigit(**av)) {
+               rule.fw_number = atoi(*av); av++; ac--;
+       }
+
+       /* Action */
+       if (ac == 0)
+               show_usage("missing action");
+       if (!strncmp(*av,"accept",strlen(*av))
+                   || !strncmp(*av,"pass",strlen(*av))
+                   || !strncmp(*av,"allow",strlen(*av))
+                   || !strncmp(*av,"permit",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_ACCEPT; av++; ac--;
+       } else if (!strncmp(*av,"count",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_COUNT; av++; ac--;
+        } else if (!strncmp(*av,"pipe",strlen(*av))) {
+                rule.fw_flg |= IP_FW_F_PIPE; av++; ac--;
+                if (!ac)
+                        show_usage("missing pipe number");
+                rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
+       } else if (!strncmp(*av,"divert",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_DIVERT; av++; ac--;
+               if (!ac)
+                       show_usage("missing %s port", "divert");
+               rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
+               if (rule.fw_divert_port == 0) {
+                       struct servent *s;
+                       setservent(1);
+                       s = getservbyname(av[-1], "divert");
+                       if (s != NULL)
+                               rule.fw_divert_port = ntohs(s->s_port);
+                       else
+                               show_usage("illegal %s port", "divert");
+               }
+       } else if (!strncmp(*av,"tee",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_TEE; av++; ac--;
+               if (!ac)
+                       show_usage("missing %s port", "tee divert");
+               rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
+               if (rule.fw_divert_port == 0) {
+                       struct servent *s;
+                       setservent(1);
+                       s = getservbyname(av[-1], "divert");
+                       if (s != NULL)
+                               rule.fw_divert_port = ntohs(s->s_port);
+                       else
+                               show_usage("illegal %s port", "tee divert");
+               }
+#ifndef IPFW_TEE_IS_FINALLY_IMPLEMENTED
+               err(EX_USAGE, "the ``tee'' action is not implemented");
+#endif
+       } else if (!strncmp(*av,"fwd",strlen(*av)) ||
+                  !strncmp(*av,"forward",strlen(*av))) {
+               struct in_addr dummyip;
+               char *pp;
+               rule.fw_flg |= IP_FW_F_FWD; av++; ac--;
+               if (!ac)
+                       show_usage("missing forwarding IP address");
+               rule.fw_fwd_ip.sin_len = sizeof(struct sockaddr_in);
+               rule.fw_fwd_ip.sin_family = AF_INET;
+               rule.fw_fwd_ip.sin_port = 0;
+               pp = strchr(*av, ':');
+               if(pp == NULL)
+                       pp = strchr(*av, ',');
+               if(pp != NULL)
+               {
+                       *(pp++) = '\0';
+                       rule.fw_fwd_ip.sin_port = lookup_port(pp, 1, 1);
+                       if(rule.fw_fwd_ip.sin_port == (unsigned int)-1)
+                               show_usage("illegal forwarding port");
+               }
+               fill_ip(&(rule.fw_fwd_ip.sin_addr), &dummyip, &ac, &av);
+               if (rule.fw_fwd_ip.sin_addr.s_addr == 0)
+                       show_usage("illegal forwarding IP address");
+
+       } else if (!strncmp(*av,"skipto",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_SKIPTO; av++; ac--;
+               if (!ac)
+                       show_usage("missing skipto rule number");
+               rule.fw_skipto_rule = strtoul(*av, NULL, 0); av++; ac--;
+       } else if ((!strncmp(*av,"deny",strlen(*av))
+                   || !strncmp(*av,"drop",strlen(*av)))) {
+               rule.fw_flg |= IP_FW_F_DENY; av++; ac--;
+       } else if (!strncmp(*av,"reject",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_REJECT; av++; ac--;
+               rule.fw_reject_code = ICMP_UNREACH_HOST;
+       } else if (!strncmp(*av,"reset",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_REJECT; av++; ac--;
+               rule.fw_reject_code = IP_FW_REJECT_RST; /* check TCP later */
+       } else if (!strncmp(*av,"unreach",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_REJECT; av++; ac--;
+               fill_reject_code(&rule.fw_reject_code, *av); av++; ac--;
+       } else {
+               show_usage("invalid action ``%s''", *av);
+       }
+
+       /* [log] */
+       if (ac && !strncmp(*av,"log",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_PRN; av++; ac--;
+       }
+
+       /* protocol */
+       if (ac == 0)
+               show_usage("missing protocol");
+       if ((proto = atoi(*av)) > 0) {
+               rule.fw_prot = proto; av++; ac--;
+       } else if (!strncmp(*av,"all",strlen(*av))) {
+               rule.fw_prot = IPPROTO_IP; av++; ac--;
+       } else if ((pe = getprotobyname(*av)) != NULL) {
+               rule.fw_prot = pe->p_proto; av++; ac--;
+       } else {
+               show_usage("invalid protocol ``%s''", *av);
+       }
+
+       if (rule.fw_prot != IPPROTO_TCP
+           && (rule.fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
+           && rule.fw_reject_code == IP_FW_REJECT_RST)
+               show_usage("``reset'' is only valid for tcp packets");
+
+       /* from */
+       if (ac && !strncmp(*av,"from",strlen(*av))) { av++; ac--; }
+       else
+               show_usage("missing ``from''");
+
+       if (ac && !strncmp(*av,"not",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_INVSRC;
+               av++; ac--;
+       }
+       if (!ac)
+               show_usage("missing arguments");
+
+       fill_ip(&rule.fw_src, &rule.fw_smsk, &ac, &av);
+
+       if (ac && (isdigit(**av) || lookup_port(*av, 1, 1) >= 0)) {
+               u_short nports = 0;
+
+               if (fill_port(&nports, rule.fw_uar.fw_pts, 0, *av))
+                       rule.fw_flg |= IP_FW_F_SRNG;
+               IP_FW_SETNSRCP(&rule, nports);
+               av++; ac--;
+       }
+
+       /* to */
+       if (ac && !strncmp(*av,"to",strlen(*av))) { av++; ac--; }
+       else
+               show_usage("missing ``to''");
+
+       if (ac && !strncmp(*av,"not",strlen(*av))) {
+               rule.fw_flg |= IP_FW_F_INVDST;
+               av++; ac--;
+       }
+       if (!ac)
+               show_usage("missing arguments");
+
+       fill_ip(&rule.fw_dst, &rule.fw_dmsk, &ac, &av);
+
+       if (ac && (isdigit(**av) || lookup_port(*av, 1, 1) >= 0)) {
+               u_short nports = 0;
+
+               if (fill_port(&nports,
+                   rule.fw_uar.fw_pts, IP_FW_GETNSRCP(&rule), *av))
+                       rule.fw_flg |= IP_FW_F_DRNG;
+               IP_FW_SETNDSTP(&rule, nports);
+               av++; ac--;
+       }
+
+       if ((rule.fw_prot != IPPROTO_TCP) && (rule.fw_prot != IPPROTO_UDP)
+           && (IP_FW_GETNSRCP(&rule) || IP_FW_GETNDSTP(&rule))) {
+               show_usage("only TCP and UDP protocols are valid"
+                   " with port specifications");
+       }
+
+       while (ac) {
+               if (!strncmp(*av,"in",strlen(*av))) { 
+                       rule.fw_flg |= IP_FW_F_IN;
+                       av++; ac--; continue;
+               }
+               if (!strncmp(*av,"out",strlen(*av))) { 
+                       rule.fw_flg |= IP_FW_F_OUT;
+                       av++; ac--; continue;
+               }
+               if (ac && !strncmp(*av,"xmit",strlen(*av))) {
+                       union ip_fw_if ifu;
+                       int byname;
+
+                       if (saw_via) {
+badviacombo:
+                               show_usage("``via'' is incompatible"
+                                   " with ``xmit'' and ``recv''");
+                       }
+                       saw_xmrc = 1;
+                       av++; ac--; 
+                       fill_iface("xmit", &ifu, &byname, ac, *av);
+                       rule.fw_out_if = ifu;
+                       rule.fw_flg |= IP_FW_F_OIFACE;
+                       if (byname)
+                               rule.fw_flg |= IP_FW_F_OIFNAME;
+                       av++; ac--; continue;
+               }
+               if (ac && !strncmp(*av,"recv",strlen(*av))) {
+                       union ip_fw_if ifu;
+                       int byname;
+
+                       if (saw_via)
+                               goto badviacombo;
+                       saw_xmrc = 1;
+                       av++; ac--; 
+                       fill_iface("recv", &ifu, &byname, ac, *av);
+                       rule.fw_in_if = ifu;
+                       rule.fw_flg |= IP_FW_F_IIFACE;
+                       if (byname)
+                               rule.fw_flg |= IP_FW_F_IIFNAME;
+                       av++; ac--; continue;
+               }
+               if (ac && !strncmp(*av,"via",strlen(*av))) {
+                       union ip_fw_if ifu;
+                       int byname = 0;
+
+                       if (saw_xmrc)
+                               goto badviacombo;
+                       saw_via = 1;
+                       av++; ac--; 
+                       fill_iface("via", &ifu, &byname, ac, *av);
+                       rule.fw_out_if = rule.fw_in_if = ifu;
+                       if (byname)
+                               rule.fw_flg |=
+                                   (IP_FW_F_IIFNAME | IP_FW_F_OIFNAME);
+                       av++; ac--; continue;
+               }
+               if (!strncmp(*av,"fragment",strlen(*av))) {
+                       rule.fw_flg |= IP_FW_F_FRAG;
+                       av++; ac--; continue;
+               }
+               if (!strncmp(*av,"ipoptions",strlen(*av))) { 
+                       av++; ac--; 
+                       if (!ac)
+                               show_usage("missing argument"
+                                   " for ``ipoptions''");
+                       fill_ipopt(&rule.fw_ipopt, &rule.fw_ipnopt, av);
+                       av++; ac--; continue;
+               }
+               if (rule.fw_prot == IPPROTO_TCP) {
+                       if (!strncmp(*av,"established",strlen(*av))) { 
+                               rule.fw_tcpf  |= IP_FW_TCPF_ESTAB;
+                               av++; ac--; continue;
+                       }
+                       if (!strncmp(*av,"setup",strlen(*av))) { 
+                               rule.fw_tcpf  |= IP_FW_TCPF_SYN;
+                               rule.fw_tcpnf  |= IP_FW_TCPF_ACK;
+                               av++; ac--; continue;
+                       }
+                       if (!strncmp(*av,"tcpflags",strlen(*av))) { 
+                               av++; ac--; 
+                               if (!ac)
+                                       show_usage("missing argument"
+                                           " for ``tcpflags''");
+                               fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av);
+                               av++; ac--; continue;
+                       }
+               }
+               if (rule.fw_prot == IPPROTO_ICMP) {
+                       if (!strncmp(*av,"icmptypes",strlen(*av))) {
+                               av++; ac--;
+                               if (!ac)
+                                       show_usage("missing argument"
+                                           " for ``icmptypes''");
+                               fill_icmptypes(rule.fw_uar.fw_icmptypes,
+                                   av, &rule.fw_flg);
+                               av++; ac--; continue;
+                       }
+               }
+               show_usage("unknown argument ``%s''", *av);
+       }
+
+       /* No direction specified -> do both directions */
+       if (!(rule.fw_flg & (IP_FW_F_OUT|IP_FW_F_IN)))
+               rule.fw_flg |= (IP_FW_F_OUT|IP_FW_F_IN);
+
+       /* Sanity check interface check, but handle "via" case separately */
+       if (saw_via) {
+               if (rule.fw_flg & IP_FW_F_IN)
+                       rule.fw_flg |= IP_FW_F_IIFACE;
+               if (rule.fw_flg & IP_FW_F_OUT)
+                       rule.fw_flg |= IP_FW_F_OIFACE;
+       } else if ((rule.fw_flg & IP_FW_F_OIFACE) && (rule.fw_flg & IP_FW_F_IN))
+               show_usage("can't check xmit interface of incoming packets");
+
+       /* frag may not be used in conjunction with ports or TCP flags */
+       if (rule.fw_flg & IP_FW_F_FRAG) {
+               if (rule.fw_tcpf || rule.fw_tcpnf)
+                       show_usage("can't mix 'frag' and tcpflags");
+
+               if (rule.fw_nports)
+                       show_usage("can't mix 'frag' and port specifications");
+       }
+
+       if (!do_quiet)
+               show_ipfw(&rule, 10, 10);
+       i = setsockopt(s, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule);
+       if (i)
+               err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_ADD");
+}
+
+static void
+zero (ac, av)
+       int ac;
+       char **av;
+{
+       av++; ac--;
+
+       if (!ac) {
+               /* clear all entries */
+               if (setsockopt(s,IPPROTO_IP,IP_FW_ZERO,NULL,0)<0)
+                       err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_ZERO");
+               if (!do_quiet)
+                       printf("Accounting cleared.\n");
+       } else {
+               struct ip_fw rule;
+               int failed = EX_OK;
+
+               memset(&rule, 0, sizeof rule);
+               while (ac) {
+                       /* Rule number */
+                       if (isdigit(**av)) {
+                               rule.fw_number = atoi(*av); av++; ac--;
+                               if (setsockopt(s, IPPROTO_IP,
+                                   IP_FW_ZERO, &rule, sizeof rule)) {
+                                       warn("rule %u: setsockopt(%s)", rule.fw_number,
+                                                "IP_FW_ZERO");
+                                       failed = EX_UNAVAILABLE;
+                               }
+                               else if (!do_quiet)
+                                       printf("Entry %d cleared\n",
+                                           rule.fw_number);
+                       } else
+                               show_usage("invalid rule number ``%s''", *av);
+               }
+               if (failed != EX_OK)
+                       exit(failed);
+       }
+}
+
+static int
+ipfw_main(ac,av)
+       int     ac;
+       char    **av;
+{
+
+       int             ch;
+       extern int      optreset; /* XXX should be declared in <unistd.h> */
+
+       if ( ac == 1 ) {
+               show_usage(NULL);
+       }
+
+       /* Set the force flag for non-interactive processes */
+       do_force = !isatty(STDIN_FILENO);
+
+       optind = optreset = 1;
+       while ((ch = getopt(ac, av, "afqtN")) != -1)
+       switch(ch) {
+               case 'a':
+                       do_acct=1;
+                       break;
+               case 'f':
+                       do_force=1;
+                       break;
+               case 'q':
+                       do_quiet=1;
+                       break;
+               case 't':
+                       do_time=1;
+                       break;
+               case 'N':
+                       do_resolv=1;
+                       break;
+               default:
+                       show_usage(NULL);
+       }
+
+       ac -= optind;
+       if (*(av+=optind)==NULL) {
+                show_usage("Bad arguments");
+       }
+
+        if (!strncmp(*av, "pipe", strlen(*av))) {
+                do_pipe = 1 ;
+                ac-- ;
+                av++ ;
+        }
+       if (!ac) {
+               show_usage("pipe requires arguments");
+       }
+        /* allow argument swapping */
+        if (ac > 1 && *av[0]>='0' && *av[0]<='9') {
+                char *p = av[0] ;
+                av[0] = av[1] ;
+                av[1] = p ;
+        }
+       if (!strncmp(*av, "add", strlen(*av))) {
+               add(ac,av);
+        } else if (do_pipe && !strncmp(*av, "config", strlen(*av))) {
+                config_pipe(ac,av);
+       } else if (!strncmp(*av, "delete", strlen(*av))) {
+               delete(ac,av);
+       } else if (!strncmp(*av, "flush", strlen(*av))) {
+               int do_flush = 0;
+
+               if ( do_force || do_quiet )
+                       do_flush = 1;
+               else {
+                       int c;
+
+                       /* Ask the user */
+                       printf("Are you sure? [yn] ");
+                       do {
+                               fflush(stdout);
+                               c = toupper(getc(stdin));
+                               while (c != '\n' && getc(stdin) != '\n')
+                                       if (feof(stdin))
+                                               return (0);
+                       } while (c != 'Y' && c != 'N');
+                       printf("\n");
+                       if (c == 'Y') 
+                               do_flush = 1;
+               }
+               if ( do_flush ) {
+                       if (setsockopt(s,IPPROTO_IP,IP_FW_FLUSH,NULL,0) < 0)
+                               err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_FLUSH");
+                       if (!do_quiet)
+                               printf("Flushed all rules.\n");
+               }
+       } else if (!strncmp(*av, "zero", strlen(*av))) {
+               zero(ac,av);
+       } else if (!strncmp(*av, "print", strlen(*av))) {
+               list(--ac,++av);
+       } else if (!strncmp(*av, "list", strlen(*av))) {
+               list(--ac,++av);
+       } else if (!strncmp(*av, "show", strlen(*av))) {
+               do_acct++;
+               list(--ac,++av);
+       } else {
+               show_usage("Bad arguments");
+       }
+       return 0;
+}
+
+int 
+main(ac, av)
+       int     ac;
+       char    **av;
+{
+#define MAX_ARGS       32
+#define WHITESP                " \t\f\v\n\r"
+       char    buf[BUFSIZ];
+       char    *a, *p, *args[MAX_ARGS], *cmd = NULL;
+       char    linename[10];
+       int     i, c, qflag, pflag, status;
+       FILE    *f = NULL;
+       pid_t   preproc = 0;
+
+       s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW );
+       if ( s < 0 )
+               err(EX_UNAVAILABLE, "socket");
+
+       setbuf(stdout,0);
+
+       if (ac > 1 && access(av[ac - 1], R_OK) == 0) {
+               qflag = pflag = i = 0;
+               lineno = 0;
+
+               while ((c = getopt(ac, av, "D:U:p:q")) != -1)
+                       switch(c) {
+                       case 'D':
+                               if (!pflag)
+                                       errx(EX_USAGE, "-D requires -p");
+                               if (i > MAX_ARGS - 2)
+                                       errx(EX_USAGE,
+                                            "too many -D or -U options");
+                               args[i++] = "-D";
+                               args[i++] = optarg;
+                               break;
+
+                       case 'U':
+                               if (!pflag)
+                                       errx(EX_USAGE, "-U requires -p");
+                               if (i > MAX_ARGS - 2)
+                                       errx(EX_USAGE,
+                                            "too many -D or -U options");
+                               args[i++] = "-U";
+                               args[i++] = optarg;
+                               break;
+
+                       case 'p':
+                               pflag = 1;
+                               cmd = optarg;
+                               args[0] = cmd;
+                               i = 1;
+                               break;
+
+                       case 'q':
+                               qflag = 1;
+                               break;
+
+                       default:
+                               show_usage(NULL);
+                       }
+
+               av += optind;
+               ac -= optind;
+               if (ac != 1)
+                       show_usage("extraneous filename arguments");
+
+               if ((f = fopen(av[0], "r")) == NULL)
+                       err(EX_UNAVAILABLE, "fopen: %s", av[0]);
+
+               if (pflag) {
+                       /* pipe through preprocessor (cpp or m4) */
+                       int pipedes[2];
+
+                       args[i] = 0;
+
+                       if (pipe(pipedes) == -1)
+                               err(EX_OSERR, "cannot create pipe");
+
+                       switch((preproc = fork())) {
+                       case -1:
+                               err(EX_OSERR, "cannot fork");
+
+                       case 0:
+                               /* child */
+                               if (dup2(fileno(f), 0) == -1 ||
+                                   dup2(pipedes[1], 1) == -1)
+                                       err(EX_OSERR, "dup2()");
+                               fclose(f);
+                               close(pipedes[1]);
+                               close(pipedes[0]);
+                               execvp(cmd, args);
+                               err(EX_OSERR, "execvp(%s) failed", cmd);
+
+                       default:
+                               /* parent */
+                               fclose(f);
+                               close(pipedes[1]);
+                               if ((f = fdopen(pipedes[0], "r")) == NULL) {
+                                       int savederrno = errno;
+
+                                       (void)kill(preproc, SIGTERM);
+                                       errno = savederrno;
+                                       err(EX_OSERR, "fdopen()");
+                               }
+                       }
+               }
+
+               while (fgets(buf, BUFSIZ, f)) {
+                       lineno++;
+                       sprintf(linename, "Line %d", lineno);
+                       args[0] = linename;
+
+                       if (*buf == '#')
+                               continue;
+                       if ((p = strchr(buf, '#')) != NULL)
+                               *p = '\0';
+                       i=1;
+                       if (qflag) args[i++]="-q";
+                       for (a = strtok(buf, WHITESP);
+                           a && i < MAX_ARGS; a = strtok(NULL, WHITESP), i++)
+                               args[i] = a;
+                       if (i == (qflag? 2: 1))
+                               continue;
+                       if (i == MAX_ARGS)
+                               errx(EX_USAGE, "%s: too many arguments", linename);
+                       args[i] = NULL;
+
+                       ipfw_main(i, args); 
+               }
+               fclose(f);
+               if (pflag) {
+                       if (waitpid(preproc, &status, 0) != -1) {
+                               if (WIFEXITED(status)) {
+                                       if (WEXITSTATUS(status) != EX_OK)
+                                               errx(EX_UNAVAILABLE,
+                                                    "preprocessor exited with status %d",
+                                                    WEXITSTATUS(status));
+                               } else if (WIFSIGNALED(status)) {
+                                       errx(EX_UNAVAILABLE,
+                                            "preprocessor exited with signal %d",
+                                            WTERMSIG(status));
+                               }
+                       }
+               }
+
+       } else
+               ipfw_main(ac,av);
+       return EX_OK;
+}
diff --git a/logger.tproj/Makefile b/logger.tproj/Makefile
new file mode 100644 (file)
index 0000000..c186192
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = logger
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = logger.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
+            h.template logger.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/logger.tproj/Makefile.postamble b/logger.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7823726
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/logger.tproj/Makefile.preamble b/logger.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/logger.tproj/PB.project b/logger.tproj/PB.project
new file mode 100644 (file)
index 0000000..796d25c
--- /dev/null
@@ -0,0 +1,34 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (logger.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            m.template, 
+            h.template, 
+            logger.1
+        ); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = logger; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/logger.tproj/h.template b/logger.tproj/h.template
new file mode 100644 (file)
index 0000000..f3c1b04
--- /dev/null
@@ -0,0 +1,11 @@
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
diff --git a/logger.tproj/logger.1 b/logger.tproj/logger.1
new file mode 100644 (file)
index 0000000..3a942e8
--- /dev/null
@@ -0,0 +1,102 @@
+.\"    $OpenBSD: logger.1,v 1.2 1996/06/26 05:35:58 deraadt Exp $
+.\"    $NetBSD: logger.1,v 1.4 1994/12/22 06:26:59 jtc Exp $
+.\"
+.\" Copyright (c) 1983, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)logger.1    8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt LOGGER 1
+.Os BSD 4.3
+.Sh NAME
+.Nm logger
+.Nd make entries in the system log
+.Sh SYNOPSIS
+.Nm logger
+.Op Fl is
+.Op Fl f Ar file
+.Op Fl p Ar pri
+.Op Fl t Ar tag
+.Op Ar message ...
+.Sh DESCRIPTION
+.Nm Logger
+provides a shell command interface to the
+.Xr syslog  3
+system log module.
+.Pp
+Options:
+.Pp
+.Bl -tag -width "message"
+.It Fl i
+Log the process id of the logger process
+with each line.
+.It Fl s
+Log the message to standard error, as well as the system log.
+.It Fl f Ar file 
+Log the specified file.
+.It Fl p Ar pri 
+Enter the message with the specified priority.
+The priority may be specified numerically or as a ``facility.level''
+pair.
+For example, ``\-p local3.info'' logs the message(s) as
+.Ar info Ns rmational
+level in the
+.Ar local3
+facility.
+The default is ``user.notice.''
+.It Fl t Ar tag 
+Mark every line in the log with the specified
+.Ar tag  .
+.It Ar message
+Write the message to log; if not specified, and the
+.Fl f
+flag is not
+provided, standard input is logged.
+.El
+.Pp
+The
+.Nm logger
+utility exits 0 on success, and >0 if an error occurs.
+.Sh EXAMPLES
+.Bd -literal -offset indent -compact
+logger System rebooted
+
+logger \-p local0.notice \-t HOSTIDM \-f /dev/idmc
+.Ed
+.Sh SEE ALSO
+.Xr syslog 3 ,
+.Xr syslogd 8
+.Sh STANDARDS
+The
+.Nm logger
+utility conforms to
+.St -p1003.2-92 .
diff --git a/logger.tproj/logger.c b/logger.tproj/logger.c
new file mode 100644 (file)
index 0000000..0ec8b27
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#define        SYSLOG_NAMES
+#include <syslog.h>
+
+int    decode __P((char *, CODE *));
+int    pencode __P((char *));
+void   usage __P((void));
+
+/*
+ * logger -- read and log utility
+ *
+ *     Reads from an input and arranges to write the result on the system
+ *     log.
+ */
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int ch, logflags, pri;
+       char *tag, buf[1024];
+
+       tag = NULL;
+       pri = LOG_NOTICE;
+       logflags = 0;
+       while ((ch = getopt(argc, argv, "f:ip:st:")) != -1)
+               switch((char)ch) {
+               case 'f':               /* file to log */
+                       if (freopen(optarg, "r", stdin) == NULL) {
+                               (void)fprintf(stderr, "logger: %s: %s.\n",
+                                   optarg, strerror(errno));
+                               exit(1);
+                       }
+                       break;
+               case 'i':               /* log process id also */
+                       logflags |= LOG_PID;
+                       break;
+               case 'p':               /* priority */
+                       pri = pencode(optarg);
+                       break;
+               case 's':               /* log to standard error */
+                       logflags |= LOG_PERROR;
+                       break;
+               case 't':               /* tag */
+                       tag = optarg;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       /* setup for logging */
+       openlog(tag ? tag : getlogin(), logflags, 0);
+       (void) fclose(stdout);
+
+       /* log input line if appropriate */
+       if (argc > 0) {
+               register char *p, *endp;
+               int len;
+
+               for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) {
+                       len = strlen(*argv);
+                       if (p + len > endp && p > buf) {
+                               syslog(pri, "%s", buf);
+                               p = buf;
+                       }
+                       if (len > sizeof(buf) - 1)
+                               syslog(pri, "%s", *argv++);
+                       else {
+                               if (p != buf)
+                                       *p++ = ' ';
+                               bcopy(*argv++, p, len);
+                               *(p += len) = '\0';
+                       }
+               }
+               if (p != buf)
+                       syslog(pri, "%s", buf);
+       } else
+               while (fgets(buf, sizeof(buf), stdin) != NULL)
+                       syslog(pri, "%s", buf);
+       exit(0);
+}
+
+/*
+ *  Decode a symbolic name to a numeric value
+ */
+int
+pencode(s)
+       register char *s;
+{
+       char *save;
+       int fac, lev;
+
+       for (save = s; *s && *s != '.'; ++s);
+       if (*s) {
+               *s = '\0';
+               fac = decode(save, facilitynames);
+               if (fac < 0) {
+                       (void)fprintf(stderr,
+                           "logger: unknown facility name: %s.\n", save);
+                       exit(1);
+               }
+               *s++ = '.';
+       }
+       else {
+               fac = 0;
+               s = save;
+       }
+       lev = decode(s, prioritynames);
+       if (lev < 0) {
+               (void)fprintf(stderr,
+                   "logger: unknown priority name: %s.\n", save);
+               exit(1);
+       }
+       return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
+}
+
+int
+decode(name, codetab)
+       char *name;
+       CODE *codetab;
+{
+       register CODE *c;
+
+       if (isdigit(*name))
+               return (atoi(name));
+
+       for (c = codetab; c->c_name; c++)
+               if (!strcasecmp(name, c->c_name))
+                       return (c->c_val);
+
+       return (-1);
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr,
+           "logger: [-is] [-f file] [-p pri] [-t tag] [ message ... ]\n");
+       exit(1);
+}
diff --git a/logger.tproj/m.template b/logger.tproj/m.template
new file mode 100644 (file)
index 0000000..1216fe5
--- /dev/null
@@ -0,0 +1,18 @@
+$$ Lines starting with $$ are not inserted into newly created files
+$$ The following substitutions are made:
+$$
+$$ $FILENAME$                e.g. foo.m
+$$ $FILENAMESANSEXTENSION$   e.g. foo
+$$ $DIRECTORY$               e.g. /tmp/MyNewApp
+$$ $PROJECTNAME$             e.g. MyNewApp
+$$ $SUBPROJECTNAME$          e.g. TheGoodPart.subproj
+$$ $USERNAME$                e.g. mwagner
+$$ $DATE$                    e.g. Jan-1-1994
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import "$FILENAMESANSEXTENSION$.h"
+
+@implementation $FILENAMESANSEXTENSION$
+
+@end
diff --git a/makedbm.tproj/Makefile b/makedbm.tproj/Makefile
new file mode 100644 (file)
index 0000000..143e661
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = makedbm
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = db.h ypdb.h ypdef.h
+
+CFILES = db.c makedbm.c ypdb.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble makedbm.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/makedbm.tproj/Makefile.postamble b/makedbm.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/makedbm.tproj/Makefile.preamble b/makedbm.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/makedbm.tproj/PB.project b/makedbm.tproj/PB.project
new file mode 100644 (file)
index 0000000..1c1cc6f
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (db.h, ypdb.h, ypdef.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (db.c, makedbm.c, ypdb.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, makedbm.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = makedbm; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/makedbm.tproj/db.c b/makedbm.tproj/db.c
new file mode 100644 (file)
index 0000000..9d5396d
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: db.c,v 1.1 1997/07/22 10:52:59 maja Exp $ */
+
+/*
+ * Copyright (c) 1997 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: db.c,v 1.1 1997/07/22 10:52:59 maja Exp $";
+#endif
+
+#include <sys/types.h>
+#include <bsd/db.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include "db.h"
+#include "ypdb.h"
+
+/*
+ * This module was created to be able to read database files created
+ * by sendmail -bi.
+ */
+
+int db_hash_list_database(database)
+char *database;
+{
+       DB *db;
+       int  status;
+       DBT key, val;
+       char path[MAXPATHLEN];
+
+       snprintf(path, sizeof(path), "%s%s", database, ".db");
+
+       db = dbopen(path, O_RDONLY, 0, DB_HASH, NULL);
+       if (db != NULL) {
+               status = db->seq(db, &key, &val, R_FIRST);
+               while (status == 0) {
+                       printf("%*.*s %*.*s\n",
+                              key.size-1, key.size-1, key.data,
+                              val.size-1, val.size-1, val.data);
+                       status = db->seq(db, &key, &val, R_NEXT);
+               }
+               db->close(db);
+               return(1);
+       }
+       return(0);
+}
+
diff --git a/makedbm.tproj/db.h b/makedbm.tproj/db.h
new file mode 100644 (file)
index 0000000..bbcf1a1
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: db.h,v 1.1 1997/07/22 10:52:59 maja Exp $ */
+
+/*
+ * Copyright (c) 1997 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MAKEDBM_DB_H_
+#define _MAKEDBM_DB_H_
+
+__BEGIN_DECLS
+int            db_hash_list_database __P((char *));
+__END_DECLS
+
+#endif /* !_MAKEDBM_DB_H_ */
+
+
diff --git a/makedbm.tproj/makedbm.8 b/makedbm.tproj/makedbm.8
new file mode 100644 (file)
index 0000000..151d29f
--- /dev/null
@@ -0,0 +1,97 @@
+.\"    $OpenBSD: makedbm.8,v 1.5 1997/07/22 10:53:00 maja Exp $
+.\" Copyright (c) 1994-97 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd July 19, 1994
+.Dt MAKEDBM 8
+.Os
+.Sh NAME
+.Nm makedbm
+.Nd create a YP database
+.Sh SYNOPSIS
+.Nm makedbm
+.Fl u Ar file
+.Nm makedbm
+.Fl U Ar file
+.Nm makedbm
+.Op Fl bls
+.Op Fl i Ar yp_input_file
+.Op Fl o Ar yp_output_file
+.Op Fl d Ar yp_domain_name
+.Op Fl m Ar yp_master_name
+.Ar infile
+.Ar outfile
+.Sh DESCRIPTION
+.Nm Makedbm
+is the utiliy in YP that creates the database file containing the YP map.
+The databse format is a slightly modified version of ndbm.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl u
+Dump a database to standard output.
+.It Fl U
+Same as
+.Fl u
+but also try 
+.Xr db 3
+hash format.
+.It Fl b
+Interdomain. Include an entry in the database informing a YP server to use
+DNS to get information about unknown hosts. This option will only have
+effect on the two maps hosts.byname and hosts.byaddr.
+.It Fl l
+Lowercase. Convert all keys to lower case before adding them to the YP
+database.
+.It Fl s 
+Secure map. Include an entry in the database informing 
+.Xr ypxfr 8
+and
+.Xr ypserv 8
+that the YP map is going to be handled as secure.
+.It Fl i Ar yp_input_file
+Include an entry the in the map with the key YP_INPUT_FILE and the argument
+as value.
+.It Fl o Ar yp_output_file
+Include an entry the in the map with the key YP_OUTPUT_FILE and the argument
+as value.
+.It Fl d Ar yp_domain_name
+Include an entry the in the map with the key YP_DOMAIN_NAME and the argument
+as value.
+.It Fl m Ar yp_master_name
+Include an entry the in the map with the key YP_MASTER_NAME and the argument
+as value.
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr db 3 ,
+.Xr ypxfr 8 ,
+.Xr ypserv 8 
+.Sh AUTHOR
+Mats O Jansson <moj@stacken.kth.se>
diff --git a/makedbm.tproj/makedbm.c b/makedbm.tproj/makedbm.c
new file mode 100644 (file)
index 0000000..8d2f73e
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: makedbm.c,v 1.9 1997/08/18 03:11:34 millert Exp $ */
+
+/*
+ * Copyright (c) 1994-97 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: makedbm.c,v 1.9 1997/08/18 03:11:34 millert Exp $";
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/errno.h>
+#include "ypdb.h"
+#include "ypdef.h"
+#include "db.h"
+
+extern char *__progname;               /* from crt0.o */
+
+/*
+ * Read one line
+ */
+
+static int read_line(fp, buf, size)
+       FILE    *fp;
+       char    *buf;
+       int     size;
+{
+       int     done;
+
+       done = 0;
+
+       do {
+               while (fgets(buf, size, fp)) {
+                       int len = strlen(buf);
+                       done += len;
+                       if (len > 1 && buf[len-2] == '\\' &&
+                                       buf[len-1] == '\n') {
+                               int ch;
+                               buf += len - 2;
+                               size -= len - 2;
+                               *buf = '\n'; buf[1] = '\0';
+                               
+                               /* Skip leading white space on next line */
+                               while ((ch = getc(fp)) != EOF &&
+                                       isascii(ch) && isspace(ch))
+                                               ;
+                               (void) ungetc(ch, fp);
+                       } else {
+                               return done;
+                       }
+               }
+       } while (size > 0 && !feof(fp));
+
+       return done;
+}
+
+void 
+add_record(db, str1, str2, check)
+       DBM     *db;
+       char    *str1, *str2;
+       int     check;
+{
+        datum   key,val;
+        int     status;
+
+       key.dptr = str1;
+       key.dsize = strlen(str1);
+       
+       if (check) {
+               val = ypdb_fetch(db,key);
+
+               if (val.dptr != NULL)
+                       return;         /* already there */
+               
+       }
+
+        val.dptr  = str2;
+       val.dsize = strlen(str2);
+       status = ypdb_store(db, key, val, YPDB_INSERT);
+       
+       if (status != 0) {
+               printf("%s: problem storing %s %s\n",__progname,str1,str2);
+               exit(1);
+       }
+}
+
+static char *
+file_date(filename)
+       char    *filename;
+{
+       struct  stat finfo;
+       static  char datestr[11];
+       int     status;
+       
+       if (strcmp(filename,"-") == 0) {
+               sprintf(datestr, "%010d", time(0));
+       } else {
+               status = stat(filename, &finfo);
+               if (status < 0) {
+                       fprintf(stderr, "%s: can't stat %s\n", __progname, filename);
+                       exit(1);
+               }       
+               sprintf(datestr, "%010d", finfo.st_mtime);
+       }
+       
+       return datestr;
+}
+
+void
+list_database(database,Uflag)
+       char    *database;
+       int     Uflag;
+{
+       DBM     *db;
+       datum   key,val;
+       
+       db = ypdb_open(database, O_RDONLY, 0444);
+       
+       if (db == NULL) {
+
+               if (Uflag != 0) {
+                       
+                       if (db_hash_list_database(database)) return;
+                       
+               }
+
+
+               fprintf(stderr, "%s: can't open database %s\n", __progname, database);
+               exit(1);
+       }
+       
+       key = ypdb_firstkey(db);
+       
+       while (key.dptr != NULL) {
+               val = ypdb_fetch(db,key);
+               printf("%*.*s %*.*s\n",
+                      key.dsize, key.dsize, key.dptr,
+                      val.dsize, val.dsize, val.dptr);
+               key = ypdb_nextkey(db);
+       }
+         
+       ypdb_close(db);
+       
+}
+
+void
+
+create_database(infile,database,
+               yp_input_file,yp_output_file,
+               yp_master_name,yp_domain_name,
+               bflag, lflag, sflag)
+       char    *infile, *database;
+       char    *yp_input_file, *yp_output_file;
+       char    *yp_master_name, *yp_domain_name;
+       int     bflag, lflag, sflag;        
+{
+       FILE    *data_file;
+       char    data_line[4096]; /* XXX: DB bsize = 4096 in ypdb.c */
+       char    myname[MAXHOSTNAMELEN];
+       int     line_no = 0;
+       int     len;
+       char    *p,*k,*v;
+       char    *slash;
+       DBM     *new_db;
+       static  char mapname[] = "ypdbXXXXXXXXXX";
+       char    db_mapname[MAXPATHLEN],db_outfile[MAXPATHLEN],
+               db_tempname[MAXPATHLEN];
+       char    empty_str[] = "";
+       
+       if (strcmp(infile,"-") == 0) {
+               data_file = stdin;
+       } else {
+               data_file = fopen(infile, "r");
+               if (errno != 0) {
+                       (void)fprintf(stderr,"%s: ",__progname);
+                       perror(infile);
+                       exit(1);
+               }
+       }
+       
+       if (strlen(database) + strlen(YPDB_SUFFIX) > MAXPATHLEN) {
+               fprintf(stderr,"%s: %s: file name too long\n",
+                       __progname, database);
+               exit(1);
+       }
+       snprintf(db_outfile, sizeof(db_outfile), "%s%s", database, YPDB_SUFFIX);
+
+       slash = strrchr(database, '/');
+       if (slash != NULL) 
+               slash[1] = 0;                   /* truncate to dir */
+       else
+               *database = 0;                  /* elminate */
+
+       /* note: database is now directory where map goes ! */
+
+       if (strlen(database) + strlen(mapname) 
+                       + strlen(YPDB_SUFFIX) > MAXPATHLEN) {
+               fprintf(stderr,"%s: %s: directory name too long\n",
+                       __progname, database);
+               exit(1);
+       }
+
+       snprintf(db_tempname, sizeof(db_tempname), "%s%s", database,
+               mapname);
+       mktemp(db_tempname);
+       snprintf(db_mapname, sizeof(db_mapname), "%s%s", db_tempname,
+               YPDB_SUFFIX);
+
+       new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444);
+       
+       while (read_line(data_file,data_line,sizeof(data_line))) {
+               
+               line_no++;
+               len =  strlen(data_line);
+               
+               /* Check if we have the whole line */ 
+               
+               if (data_line[len-1] != '\n') {
+                       fprintf(stderr, "line %d in \"%s\" is too long",
+                               line_no, infile);
+               } else {
+                       data_line[len-1] = '\0';
+               }
+               
+               p = (char *) &data_line;
+               
+               k  = p;                              /* save start of key */
+               while (!isspace(*p)) {              /* find first "space" */
+                       if (lflag && isupper(*p))   /* if force lower case */
+                               *p = tolower(*p);   /* fix it */
+                       p++;
+               };
+               while (isspace(*p)) {           /* replace space with <NUL> */
+                       *p = '\0';
+                       p++;
+               };
+               
+               v = p;                          /* save start of value */
+               while(*p != '\0') { p++; };     /* find end of string */
+               
+               add_record(new_db, k, v, TRUE); /* save record */
+               
+       }
+       
+       if (strcmp(infile,"-") != 0) {
+               (void) fclose(data_file);
+       }
+       
+       add_record(new_db, YP_LAST_KEY, file_date(infile), FALSE);
+       
+       if (yp_input_file) {
+               add_record(new_db, YP_INPUT_KEY, yp_input_file, FALSE);
+       }
+       
+       if (yp_output_file) {
+               add_record(new_db, YP_OUTPUT_KEY, yp_output_file, FALSE);
+       }
+       
+       if (yp_master_name) {
+               add_record(new_db, YP_MASTER_KEY, yp_master_name, FALSE);
+       } else {
+               gethostname(myname, sizeof(myname) - 1);
+               add_record(new_db, YP_MASTER_KEY, myname, FALSE);
+       }
+       
+       if (yp_domain_name) {
+               add_record(new_db, YP_DOMAIN_KEY, yp_domain_name, FALSE);
+       }
+       
+       if (bflag) {
+               add_record(new_db, YP_INTERDOMAIN_KEY, empty_str, FALSE);
+       }
+
+       if (sflag) {
+               add_record(new_db, YP_SECURE_KEY, empty_str, FALSE);
+       }
+
+       ypdb_close(new_db);
+       if (rename(db_mapname,db_outfile) < 0) {
+               perror("rename");
+               fprintf(stderr,"rename %s -> %s failed!\n", db_mapname,
+                       db_outfile);
+               exit(1);
+       }
+       
+}
+
+int
+main (argc,argv)
+       int     argc;
+       char    *argv[];
+{
+       int     aflag, uflag, bflag, lflag, sflag, Uflag;
+       char    *yp_input_file, *yp_output_file;
+       char    *yp_master_name,*yp_domain_name;
+       char    *infile,*outfile;
+       int     usage = 0;
+       int     ch;
+       
+       extern int optind;
+       
+       yp_input_file = yp_output_file = NULL;
+       yp_master_name = yp_domain_name = NULL;
+       aflag = uflag = bflag = lflag = sflag = Uflag = 0;
+       infile = outfile = NULL;
+       
+       while ((ch = getopt(argc, argv, "Ublsui:o:m:d:")) != -1)
+               switch (ch) {
+                       case 'U': 
+                               uflag++;
+                               Uflag++;
+                               break;
+                       case 'b':
+                               bflag++;
+                               aflag++;
+                               break;
+                       case 'l':
+                               lflag++;
+                               aflag++;
+                               break;
+                       case 's':
+                               sflag++;
+                               aflag++;
+                               break;
+                       case 'i':
+                               yp_input_file = argv[optind];
+                               aflag++;
+                               break;
+                       case 'o':
+                               yp_output_file = argv[optind];
+                               aflag++;
+                               break;
+                       case 'm':
+                               yp_master_name = argv[optind];
+                               aflag++;
+                               break;
+                       case 'd':
+                               yp_domain_name = argv[optind];
+                               aflag++;
+                               break;
+                       case 'u':
+                               uflag++;
+                               break;
+                       default:
+                               usage++;
+                               break;
+               }
+       
+       if ((uflag != 0) && (aflag != 0)) {
+               usage++;
+       } else {
+               
+               if (uflag != 0) {
+                       if (argc == (optind + 1)) {
+                               infile = argv[optind];
+                       } else {
+                               usage++;
+                       }
+               } else {
+                       if (argc == (optind + 2)) {
+                               infile = argv[optind];
+                               outfile = argv[optind+1];
+                       } else {
+                               usage++;
+                       }
+               }
+       }
+       
+       if (usage) {
+               fprintf(stderr,"%s%s%s",
+                       "usage:\tmakedbm [-u|-U] file\n\tmakedbm [-bls]",
+                       " [-i YP_INPUT_FILE] [-o YP_OUTPUT_FILE]\n\t\t",
+                       "[-d YP_DOMAIN_NAME] [-m YP_MASTER_NAME] infile outfile\n");
+               exit(1);
+       }
+       
+       if (uflag != 0) {
+               list_database(infile,Uflag);
+       } else {
+               create_database(infile,outfile,
+                               yp_input_file,yp_output_file,
+                               yp_master_name,yp_domain_name,
+                               bflag, lflag, sflag);
+       }
+       
+       return(0);
+       
+}
diff --git a/makedbm.tproj/ypdb.c b/makedbm.tproj/ypdb.c
new file mode 100644 (file)
index 0000000..c9bd178
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ypdb.h"
+
+#ifdef YPDB_PATCH
+extern DBM *__hash_open();
+#else
+extern DBM *__bt_open();
+#endif
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+       char path[MAXPATHLEN];
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       char path[MAXPATHLEN];
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       db = (DBM *)__bt_open(path, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open_suf(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       return ((DBM *)__hash_open(file, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       db = (DBM *)__bt_open(file, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+extern void
+ypdb_close(db)
+       DBM *db;
+{
+       (void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_fetch(db, key)
+       DBM *db;
+       datum key;
+{
+       datum retval;
+       int status;
+
+       status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+       if (status) {
+               retval.dptr = NULL;
+               retval.dsize = 0;
+       }
+       return (retval);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_firstkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_nextkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_setkey(db, key)
+       DBM *db;
+        datum key;
+{
+       int status;
+       datum retdata;
+#ifdef YPDB_PATCH
+       datum retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       while ((retkey.dptr != NULL) &&
+              ((retkey.dsize != key.dsize) ||
+               (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) {
+         status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+         if (status)
+               retkey.dptr = NULL;
+       };
+       return (retkey);
+#else
+       status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR);
+       if (status)
+               key.dptr = NULL;
+       return (key);
+#endif
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ */
+
+int
+ypdb_delete(db, key)
+       DBM *db;
+       datum key;
+{
+       int status;
+
+       status = (db->del)(db, (DBT *)&key, 0);
+       if (status)
+               return (-1);
+       else
+               return (0);
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ *      1 if YPDB_INSERT and entry exists
+ */
+
+int
+ypdb_store(db, key, content, flags)
+       DBM *db;
+       datum key, content;
+       int flags;
+{
+       return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+           (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0));
+}
+
diff --git a/makedbm.tproj/ypdb.h b/makedbm.tproj/ypdb.h
new file mode 100644 (file)
index 0000000..9afbad5
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDB_H_
+#define _YPDB_H_
+
+#ifndef _DB_H_
+#include <bsd/db.h>
+#endif
+
+#define YPDB_SUFFIX    ".db"
+
+/* Flags to ypdb_store(). */
+#define YPDB_INSERT      0
+#define YPDB_REPLACE     1
+
+#ifndef DATUM
+typedef struct {
+       char    *dptr;
+       int     dsize;
+} datum;
+#define DATUM
+#endif
+
+typedef DB DBM;
+
+__BEGIN_DECLS
+void    ypdb_close __P((DBM *));
+datum   ypdb_fetch __P((DBM *, datum));
+datum   ypdb_firstkey __P((DBM *));
+datum   ypdb_nextkey __P((DBM *));
+datum   ypdb_setkey __P((DBM *, datum));
+DBM     *ypdb_open __P((const char *, int, int));
+DBM     *ypdb_open_suf __P((const char *, int, int));
+int     ypdb_store __P((DBM *, datum, datum, int));
+__END_DECLS
+
+#endif /* !_YPDB_H_ */
diff --git a/makedbm.tproj/ypdef.h b/makedbm.tproj/ypdef.h
new file mode 100644 (file)
index 0000000..89970d7
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDEF_H_
+#define _YPDEF_H_
+
+#define YP_DB_PATH "/var/yp"
+#define YP_LAST_KEY        "YP_LAST_MODIFIED"
+#define YP_LAST_LEN       (sizeof(YP_LAST_KEY)-1)
+#define YP_INPUT_KEY       "YP_INPUT_FILE"
+#define YP_INPUT_LEN      (sizeof(YP_INPUT_KEY)-1)
+#define YP_OUTPUT_KEY      "YP_OUTPUT_FILE"
+#define YP_OUTPUT_LEN     (sizeof(YP_OUTPUT_KEY)-1)
+#define YP_MASTER_KEY      "YP_MASTER_NAME"
+#define YP_MASTER_LEN     (sizeof(YP_MASTER_KEY)-1)
+#define YP_DOMAIN_KEY      "YP_DOMAIN_NAME"
+#define YP_DOMAIN_LEN     (sizeof(YP_DOMAIN_KEY)-1)
+#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN"
+#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1)
+#define YP_SECURE_KEY      "YP_SECURE"
+#define YP_SECURE_LEN      (sizeof(YP_SECURE_KEY)-1)
+
+#define MAX_LAST_LEN 10
+#define MAX_MASTER_LEN 255
+#define YP_HOSTNAME "hosts.byname"
+#define YP_HOSTADDR "hosts.byaddr"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define YPXFR_PROC "/usr/sbin/ypxfr"
+#define YPPUSH_PROC "/usr/sbin/yppush"
+#define YPSERV_PID_PATH "/var/run/ypserv.pid"
+#define YP_SECURENET_FILE "/var/yp/securenet"
+
+#endif /* !_YPDEF_H_ */
diff --git a/natd.tproj/Makefile b/natd.tproj/Makefile
new file mode 100644 (file)
index 0000000..ad7ef52
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Generated by the Apple Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = natd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = natd.h
+
+CFILES = icmp.c natd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble natd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = -lalias
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/natd.tproj/Makefile.postamble b/natd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..acc4f20
--- /dev/null
@@ -0,0 +1,104 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+install-man-page:
+       install -d $(DSTROOT)/usr/share/man/man8
+       install -c -m 444 natd.8 $(DSTROOT)/usr/share/man/man8/natd.8
+
diff --git a/natd.tproj/Makefile.preamble b/natd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..a4606c6
--- /dev/null
@@ -0,0 +1,140 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+DSTROOT = $(HOME)
+
+AFTER_INSTALL += install-man-page
+
diff --git a/natd.tproj/PB.project b/natd.tproj/PB.project
new file mode 100644 (file)
index 0000000..a64fa2f
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (natd.h); 
+        OTHER_LIBS = (alias); 
+        OTHER_LINKED = (icmp.c, natd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, natd.8); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = natd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = /Library/Executables; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/natd.tproj/icmp.c b/natd.tproj/icmp.c
new file mode 100644 (file)
index 0000000..10d3bda
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * natd - Network Address Translation Daemon for FreeBSD.
+ *
+ * This software is provided free of charge, with no 
+ * warranty of any kind, either expressed or implied.
+ * Use at your own risk.
+ * 
+ * You may copy, modify and distribute this software (icmp.c) freely.
+ *
+ * Ari Suutari <suutari@iki.fi>
+ *
+ *     $Id: icmp.c,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <netdb.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#include <alias.h>
+
+#include "natd.h"
+
+int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu)
+{
+       char                    icmpBuf[IP_MAXPACKET];
+       struct ip*              ip;
+       struct icmp*            icmp;
+       int                     icmpLen;
+       int                     failBytes;
+       int                     failHdrLen;
+       struct sockaddr_in      addr;
+       int                     wrote;
+       struct in_addr          swap;
+/*
+ * Don't send error if packet is
+ * not the first fragment.
+ */
+       if (ntohs (failedDgram->ip_off) & ~(IP_MF | IP_DF))
+               return 0;
+/*
+ * Dont respond if failed datagram is ICMP.
+ */
+       if (failedDgram->ip_p == IPPROTO_ICMP)
+               return 0;
+/*
+ * Start building the message.
+ */
+       ip   = (struct ip*) icmpBuf;
+       icmp = (struct icmp*) (icmpBuf + sizeof (struct ip));
+/*
+ * Complete ICMP part.
+ */
+       icmp->icmp_type         = ICMP_UNREACH;
+       icmp->icmp_code         = ICMP_UNREACH_NEEDFRAG;
+       icmp->icmp_cksum        = 0;
+       icmp->icmp_void         = 0;
+       icmp->icmp_nextmtu      = htons (mtu);
+/*
+ * Copy header + 64 bits of original datagram.
+ */
+       failHdrLen = (failedDgram->ip_hl << 2);
+       failBytes  = failedDgram->ip_len - failHdrLen;
+       if (failBytes > 8)
+               failBytes = 8;
+
+       failBytes += failHdrLen;
+       icmpLen    = ICMP_MINLEN + failBytes;
+
+       memcpy (&icmp->icmp_ip, failedDgram, failBytes);
+/*
+ * Calculate checksum.
+ */
+       icmp->icmp_cksum = PacketAliasInternetChecksum ((u_short*) icmp,
+                                                       icmpLen);
+/*
+ * Add IP header using old IP header as template.
+ */
+       memcpy (ip, failedDgram, sizeof (struct ip));
+
+       ip->ip_v        = 4;
+       ip->ip_hl       = 5;
+       ip->ip_len      = htons (sizeof (struct ip) + icmpLen);
+       ip->ip_p        = IPPROTO_ICMP;
+       ip->ip_tos      = 0;
+
+       swap = ip->ip_dst;
+       ip->ip_dst = ip->ip_src;
+       ip->ip_src = swap;
+
+       PacketAliasIn ((char*) ip, IP_MAXPACKET);
+
+       addr.sin_family         = AF_INET;
+       addr.sin_addr           = ip->ip_dst;
+       addr.sin_port           = 0;
+/*
+ * Put packet into processing queue.
+ */
+       wrote = sendto (sock, 
+                       icmp,
+                       icmpLen,
+                       0,
+                       (struct sockaddr*) &addr,
+                       sizeof addr);
+       
+       if (wrote != icmpLen)
+               Warn ("Cannot send ICMP message.");
+
+       return 1;
+}
+
+
diff --git a/natd.tproj/natd.8 b/natd.tproj/natd.8
new file mode 100644 (file)
index 0000000..1d1cb7f
--- /dev/null
@@ -0,0 +1,426 @@
+.\" manual page [] for natd 1.4
+.\"    $Id: natd.8,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $
+.Dd 15 April 1997
+.Os FreeBSD
+.Dt NATD 8
+.Sh NAME
+.Nm natd
+.Nd
+Network Address Translation Daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl ldsmvu
+.Op Fl dynamic
+.Op Fl i Ar inport
+.Op Fl o Ar outport
+.Op Fl p Ar port
+.Op Fl a Ar address
+.Op Fl n Ar interface
+.Op Fl f Ar configfile
+
+.Nm
+.Op Fl log
+.Op Fl deny_incoming
+.Op Fl log_denied
+.Op Fl use_sockets
+.Op Fl same_ports
+.Op Fl verbose
+.Op Fl log_facility Ar facility_name
+.Op Fl unregistered_only
+.Op Fl dynamic
+.Op Fl inport Ar inport
+.Op Fl outport Ar outport
+.Op Fl port Ar port
+.Op Fl alias_address Ar address
+.Op Fl interface Ar interface
+.Op Fl config Ar configfile
+.Op Fl redirect_port Ar linkspec
+.Op Fl redirect_address Ar localIP publicIP
+.Op Fl reverse
+.Op Fl proxy_only
+.Op Fl proxy_rule Ar proxyspec
+.Op Fl pptpalias Ar localIP
+
+.Sh DESCRIPTION
+This program provides a Network Address Translation facility for use
+with
+.Xr divert 4
+sockets under FreeBSD.  It is intended for use with NICs - if you want
+to do NAT on a PPP link, use the -alias switch to
+.Xr ppp 8 .
+
+.Pp
+.Nm Natd
+normally runs in the background as a daemon.  It is passed raw IP packets
+as they travel into and out of the machine, and will possibly change these
+before re-injecting them back into the IP packet stream.
+
+.Pp
+.Nm Natd
+changes all packets destined for another host so that their source
+IP number is that of the current machine.  For each packet changed
+in this manner, an internal table entry is created to record this
+fact.  The source port number is also changed to indicate the
+table entry applying to the packet.  Packets that are received with
+a target IP of the current host are checked against this internal
+table.  If an entry is found, it is used to determine the correct
+target IP number and port to place in the packet.
+
+.Pp
+The following command line options are available.
+.Bl -tag -width Fl
+
+.It Fl log | l
+Log various aliasing statistics and information to the file
+.Pa /var/log/alias.log .
+This file is truncated each time natd is started.
+
+.It Fl deny_incoming | d
+Reject packets destined for the current IP number that have no entry
+in the internal translation table.
+
+.It Fl log_denied
+Log denied incoming packets via syslog (see also log_facility)
+
+.It Fl log_facility Ar facility_name
+Use specified log facility when logging information via syslog.
+Facility names are as in
+.Xr syslog.conf 5
+
+.It Fl use_sockets | s
+Allocate a
+.Xr socket 2
+in order to establish an FTP data or IRC DCC send connection.  This
+option uses more system resources, but guarantees successful connections
+when port numbers conflict.
+
+.It Fl same_ports | m
+Try to keep the same port number when altering outgoing packets.
+With this option, protocols such as RPC will have a better chance
+of working.  If it is not possible to maintain the port number, it
+will be silently changed as per normal.
+
+.It Fl verbose | v
+Don't call
+.Xr fork 2
+or
+.Xr daemon 3
+on startup.  Instead, stay attached to the controling terminal and
+display all packet alterations to the standard output.  This option
+should only be used for debugging purposes.
+
+.It Fl unregistered_only | u
+Only alter outgoing packets with an unregistered source address.
+According to rfc 1918, unregistered source addresses are 10.0.0.0/8,
+172.16.0.0/12 and 192.168.0.0/16.
+
+.It Fl redirect_port Ar proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]]
+Redirect incoming connections arriving to given port to another host and port.
+Proto is either tcp or udp, targetIP is the desired target IP
+number, targetPORT is the desired target PORT number, aliasPORT
+is the requested PORT number and aliasIP is the aliasing address.
+RemoteIP and remotePORT can be used to specify the connection
+more accurately if necessary.
+For example, the argument
+
+.Ar tcp inside1:telnet 6666
+
+means that tcp packets destined for port 6666 on this machine will
+be sent to the telnet port on the inside1 machine.
+
+.It Fl redirect_address Ar localIP publicIP
+Redirect traffic for public IP address to a machine on the local
+network. This function is known as "static NAT". Normally static NAT
+is useful if your ISP has allocated a small block of IP addresses to you,
+but it can even be used in the case of single address:
+
+  redirect_address 10.0.0.8 0.0.0.0
+
+The above command would redirect all incoming traffic
+to machine 10.0.0.8.
+
+If several address aliases specify the same public address
+as follows
+
+  redirect_address 192.168.0.2 public_addr
+  redirect_address 192.168.0.3 public_addr
+  redirect_address 192.168.0.4 public_addr
+  
+the incoming traffic will be directed to the last
+translated local address (192.168.0.4), but outgoing
+traffic to the first two addresses will still be aliased
+to specified public address.
+
+.It Fl dynamic
+If the
+.Fl n
+or
+.Fl interface
+option is used,
+.Nm
+will monitor the routing socket for alterations to the
+.Ar interface
+passed.  If the interfaces IP number is changed,
+.Nm
+will dynamically alter its concept of the alias address.
+
+.It Fl i | inport Ar inport
+Read from and write to
+.Ar inport ,
+treating all packets as packets coming into the machine.
+
+.It Fl o | outport Ar outport
+Read from and write to
+.Ar outport ,
+treating all packets as packets going out of the machine.
+
+.It Fl p | port Ar port
+Read from and write to
+.Ar port ,
+distinguishing packets as incoming our outgoing using the rules specified in
+.Xr divert 4 .
+If
+.Ar port
+is not numeric, it is searched for in the
+.Pa /etc/services
+database using the
+.Xr getservbyname 3
+function.  If this flag is not specified, the divert port named natd will
+be used as a default.  An example entry in the
+.Pa /etc/services
+database would be:
+
+  natd   8668/divert  # Network Address Translation socket
+
+Refer to
+.Xr services 5
+for further details.
+
+.It Fl a | alias_address Ar address
+Use
+.Ar address
+as the alias address.  If this option is not specified, the
+.Fl n
+or
+.Fl interface
+option must be used.  The specified address should be the address assigned
+to the public network interface.
+.Pp
+All data passing out through this addresses interface will be rewritten
+with a source address equal to
+.Ar address .
+All data arriving at the interface from outside will be checked to
+see if it matches any already-aliased outgoing connection.  If it does,
+the packet is altered accordingly.  If not, all
+.Fl redirect_port
+and
+.Fl redirect_address
+assignments are checked and actioned.  If no other action can be made,
+and if
+.Fl deny_incoming
+is not specified, the packet is delivered to the local machine and port
+as specified in the packet.
+
+.It Fl n | interface Ar interface
+Use
+.Ar interface
+to determine the alias address.  If there is a possibility that the
+IP number associated with
+.Ar interface
+may change, the
+.Fl dynamic
+flag should also be used.  If this option is not specified, the
+.Fl a
+or
+.Fl alias_address
+flag must be used.
+.Pp
+The specified
+.Ar interface
+must be the public network interface.
+.It Fl f | config Ar configfile
+Read configuration from
+.Ar configfile .
+.Ar Configfile
+contains a list of options, one per line in the same form as the
+long form of the above command line flags.  For example, the line
+
+  alias_address 158.152.17.1
+
+would specify an alias address of 158.152.17.1.  Options that don't
+take an argument are specified with an option of
+.Ar yes
+or
+.Ar no
+in the configuration file.  For example, the line
+
+  log yes
+
+is synonomous with
+.Fl log .
+Empty lines and lines beginning with '#' are ignored.
+
+.It Fl reverse
+Reverse operation of natd. This can be useful in some 
+transparent proxying situations when outgoing traffic
+is redirected to the local machine and natd is running on the
+incoming interface (it usually runs on the outgoing interface).
+
+.It Fl proxy_only
+Force natd to perform transparent proxying
+only. Normal address translation is not performed.
+
+.It Fl proxy_rule Ar [type encode_ip_hdr|encode_tcp_stream] port xxxx server a.b.c.d:yyyy
+Enable transparent proxying. Packets with the given port going through this
+host to any other host are redirected to the given server and port.
+Optionally, the original target address can be encoded into the packet. Use 
+.Dq encode_ip_hdr
+to put this information into the IP option field or
+.Dq encode_tcp_stream
+to inject the data into the beginning of the TCP stream.
+
+.It Fl pptpalias Ar localIP
+Allow PPTP packets to go to the defined localIP address. PPTP is a VPN or secure
+IP tunneling technology being developed primarily by Microsoft. For its encrypted traffic,
+it uses an old IP encapsulation protocol called GRE (47). This
+natd option will translate any traffic of this protocol to a
+single, specified IP address. This would allow either one client or one server 
+to be serviced with natd. If you are setting up a server, don't forget to allow the TCP traffic
+for the PPTP setup. For a client or server, you must allow GRE (protocol 47) if you have firewall lists active.
+
+.El
+
+.Sh RUNNING NATD
+The following steps are necessary before attempting to run
+.Nm natd :
+
+.Bl -enum
+.It
+Get FreeBSD version 2.2 or higher.  Versions before this do not support
+.Xr divert 4
+sockets.
+
+.It
+Build a custom kernel with the following options:
+
+  options IPFIREWALL
+  options IPDIVERT
+
+Refer to the handbook for detailed instructions on building a custom
+kernel.
+
+.It
+Ensure that your machine is acting as a gateway.  This can be done by
+specifying the line
+
+  gateway_enable=YES
+
+in
+.Pa /etc/rc.conf ,
+or using the command
+
+  sysctl -w net.inet.ip.forwarding=1
+
+.It
+If you wish to use the
+.Fl n
+or
+.Fl interface
+flags, make sure that your interface is already configured.  If, for
+example, you wish to specify tun0 as your
+.Ar interface ,
+and you're using
+.Xr ppp 8
+on that interface, you must make sure that you start
+.Nm ppp
+prior to starting
+.Nm natd .
+
+.It
+Create an entry in
+.Pa /etc/services :
+
+  natd          8668/divert  # Network Address Translation socket
+
+This gives a default for the
+.Fl p
+or
+.Fl port
+flag.
+
+.El
+.Pp
+Running
+.Nm
+is fairly straight forward.  The line
+
+  natd -interface ed0
+
+should suffice in most cases (substituting the correct interface name).  Once
+.Nm
+is running, you must ensure that traffic is diverted to natd:
+
+.Bl -enum
+.It
+You will need to adjust the
+.Pa /etc/rc.firewall
+script to taste.  If you're not interested in having a firewall, the
+following lines will do:
+
+  /sbin/ipfw -f flush
+  /sbin/ipfw add divert natd all from any to any via ed0
+  /sbin/ipfw add pass all from any to any
+
+The second line depends on your interface (change ed0 as appropriate)
+and assumes that you've updated
+.Pa /etc/services
+with the natd entry as above.  If you specify real firewall rules, it's
+best to specify line 2 at the start of the script so that
+.Nm
+sees all packets before they are dropped by the firewall.  The firewall
+rules will be run again on each packet after translation by
+.Nm natd ,
+minus any divert rules.
+
+.It
+Enable your firewall by setting
+
+  firewall_enable=YES
+
+in
+.Pa /etc/rc.conf .
+This tells the system startup scripts to run the
+.Pa /etc/rc.firewall
+script.  If you don't wish to reboot now, just run this by hand from the
+console.  NEVER run this from a virtual session unless you put it into
+the background.  If you do, you'll lock yourself out after the flush
+takes place, and execution of
+.Pa /etc/rc.firewall
+will stop at this point - blocking all accesses permanently.  Running
+the script in the background should be enough to prevent this disaster.
+
+.El
+
+.Sh SEE ALSO
+.Xr getservbyname 2 ,
+.Xr socket 2 ,
+.Xr divert 4 ,
+.Xr services 5 ,
+.Xr ipfw 8
+
+.Sh AUTHORS
+This program is the result of the efforts of many people at different
+times:
+
+.An Archie Cobbs Aq archie@whistle.com
+(divert sockets)
+.An Charles Mott Aq cmott@srv.net
+(packet aliasing)
+.An Eivind Eklund Aq perhaps@yes.no
+(IRC support & misc additions)
+.An Ari Suutari Aq suutari@iki.fi
+(natd)
+.An Dru Nelson Aq dnelson@redwoodsoft.com
+(PPTP support)
+.An Brian Somers Aq brian@awfulhak.org
+(glue)
diff --git a/natd.tproj/natd.c b/natd.tproj/natd.c
new file mode 100644 (file)
index 0000000..bbb8678
--- /dev/null
@@ -0,0 +1,1578 @@
+/*
+ * natd - Network Address Translation Daemon for FreeBSD.
+ *
+ * This software is provided free of charge, with no 
+ * warranty of any kind, either expressed or implied.
+ * Use at your own risk.
+ * 
+ * You may copy, modify and distribute this software (natd.c) freely.
+ *
+ * Ari Suutari <suutari@iki.fi>
+ *
+ *     $Id: natd.c,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $
+ */
+
+#define SYSLOG_NAMES
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <arpa/inet.h>
+
+#include <alias.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "natd.h"
+
+/* 
+ * Default values for input and output
+ * divert socket ports.
+ */
+
+#define        DEFAULT_SERVICE "natd"
+
+/*
+ * Definition of a port range, and macros to deal with values.
+ * FORMAT:  HI 16-bits == first port in range, 0 == all ports.
+ *          LO 16-bits == number of ports in range
+ * NOTES:   - Port values are not stored in network byte order.
+ */
+
+typedef u_long port_range;
+
+#define GETLOPORT(x)     ((x) >> 0x10)
+#define GETNUMPORTS(x)   ((x) & 0x0000ffff)
+#define GETHIPORT(x)     (GETLOPORT((x)) + GETNUMPORTS((x)))
+
+/* Set y to be the low-port value in port_range variable x. */
+#define SETLOPORT(x,y)   ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
+
+/* Set y to be the number of ports in port_range variable x. */
+#define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
+
+/*
+ * Function prototypes.
+ */
+
+static void    DoAliasing (int fd, int direction);
+static void    DaemonMode (void);
+static void    HandleRoutingInfo (int fd);
+static void    Usage (void);
+static char*   FormatPacket (struct ip*);
+static void    PrintPacket (struct ip*);
+static void    SyslogPacket (struct ip*, int priority, const char *label);
+static void    SetAliasAddressFromIfName (char* ifName);
+static void    InitiateShutdown (int);
+static void    Shutdown (int);
+static void    RefreshAddr (int);
+static void    ParseOption (const char* option, const char* parms, int cmdLine);
+static void    ReadConfigFile (const char* fileName);
+static void    SetupPortRedirect (const char* parms);
+static void    SetupAddressRedirect (const char* parms);
+static void    SetupPptpAlias (const char* parms);
+static void    StrToAddr (const char* str, struct in_addr* addr);
+static u_short  StrToPort (const char* str, const char* proto);
+static int      StrToPortRange (const char* str, const char* proto, port_range *portRange);
+static int     StrToProto (const char* str);
+static int      StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange);
+static void    ParseArgs (int argc, char** argv);
+static void    FlushPacketBuffer (int fd);
+
+/*
+ * Globals.
+ */
+
+static int                     verbose;
+static         int                     background;
+static int                     running;
+static int                     assignAliasAddr;
+static char*                   ifName;
+static  int                    ifIndex;
+static u_short                 inPort;
+static u_short                 outPort;
+static u_short                 inOutPort;
+static struct in_addr          aliasAddr;
+static         int                     dynamicMode;
+static  int                    ifMTU;
+static int                     aliasOverhead;
+static         int                     icmpSock;
+static char                    packetBuf[IP_MAXPACKET];
+static         int                     packetLen;
+static struct sockaddr_in      packetAddr;
+static         int                     packetSock;
+static         int                     packetDirection;
+static  int                    dropIgnoredIncoming;
+static  int                    logDropped;
+static int                     logFacility;
+
+int main (int argc, char** argv)
+{
+       int                     divertIn;
+       int                     divertOut;
+       int                     divertInOut;
+       int                     routeSock;
+       struct sockaddr_in      addr;
+       fd_set                  readMask;
+       fd_set                  writeMask;
+       int                     fdMax;
+/* 
+ * Initialize packet aliasing software.
+ * Done already here to be able to alter option bits
+ * during command line and configuration file processing.
+ */
+       PacketAliasInit ();
+/*
+ * Parse options.
+ */
+       inPort                  = 0;
+       outPort                 = 0;
+       verbose                 = 0;
+       inOutPort               = 0;
+       ifName                  = NULL;
+       ifMTU                   = -1;
+       background              = 0;
+       running                 = 1;
+       assignAliasAddr         = 0;
+       aliasAddr.s_addr        = INADDR_NONE;
+       aliasOverhead           = 12;
+       dynamicMode             = 0;
+       logDropped              = 0;
+       logFacility             = LOG_DAEMON;
+/*
+ * Mark packet buffer empty.
+ */
+       packetSock              = -1;
+       packetDirection         = DONT_KNOW;
+
+       ParseArgs (argc, argv);
+/*
+ * Open syslog channel.
+ */
+       openlog ("natd", LOG_CONS | LOG_PID, logFacility);
+/*
+ * Check that valid aliasing address has been given.
+ */
+       if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL)
+               errx (1, "aliasing address not given");
+
+       if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL)
+               errx (1, "both alias address and interface "
+                        "name are not allowed");
+/*
+ * Check that valid port number is known.
+ */
+       if (inPort != 0 || outPort != 0)
+               if (inPort == 0 || outPort == 0)
+                       errx (1, "both input and output ports are required");
+
+       if (inPort == 0 && outPort == 0 && inOutPort == 0)
+               ParseOption ("port", DEFAULT_SERVICE, 0);
+
+/*
+ * Check if ignored packets should be dropped.
+ */
+       dropIgnoredIncoming = PacketAliasSetMode (0, 0);
+       dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING;
+/*
+ * Create divert sockets. Use only one socket if -p was specified
+ * on command line. Otherwise, create separate sockets for
+ * outgoing and incoming connnections.
+ */
+       if (inOutPort) {
+
+               divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+               if (divertInOut == -1)
+                       Quit ("Unable to create divert socket.");
+
+               divertIn  = -1;
+               divertOut = -1;
+/*
+ * Bind socket.
+ */
+
+               addr.sin_family         = AF_INET;
+               addr.sin_addr.s_addr    = INADDR_ANY;
+               addr.sin_port           = inOutPort;
+
+               if (bind (divertInOut,
+                         (struct sockaddr*) &addr,
+                         sizeof addr) == -1)
+                       Quit ("Unable to bind divert socket.");
+       }
+       else {
+
+               divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+               if (divertIn == -1)
+                       Quit ("Unable to create incoming divert socket.");
+
+               divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+               if (divertOut == -1)
+                       Quit ("Unable to create outgoing divert socket.");
+
+               divertInOut = -1;
+
+/*
+ * Bind divert sockets.
+ */
+
+               addr.sin_family         = AF_INET;
+               addr.sin_addr.s_addr    = INADDR_ANY;
+               addr.sin_port           = inPort;
+
+               if (bind (divertIn,
+                         (struct sockaddr*) &addr,
+                         sizeof addr) == -1)
+                       Quit ("Unable to bind incoming divert socket.");
+
+               addr.sin_family         = AF_INET;
+               addr.sin_addr.s_addr    = INADDR_ANY;
+               addr.sin_port           = outPort;
+
+               if (bind (divertOut,
+                         (struct sockaddr*) &addr,
+                         sizeof addr) == -1)
+                       Quit ("Unable to bind outgoing divert socket.");
+       }
+/*
+ * Create routing socket if interface name specified.
+ */
+       if (ifName && dynamicMode) {
+
+               routeSock = socket (PF_ROUTE, SOCK_RAW, 0);
+               if (routeSock == -1)
+                       Quit ("Unable to create routing info socket.");
+       }
+       else
+               routeSock = -1;
+/*
+ * Create socket for sending ICMP messages.
+ */
+       icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
+       if (icmpSock == -1)
+               Quit ("Unable to create ICMP socket.");
+
+/*
+ * And disable reads for the socket, otherwise it slowly fills
+ * up with received icmps which we do not use.
+ */
+       shutdown(icmpSock, SHUT_RD);
+
+/*
+ * Become a daemon unless verbose mode was requested.
+ */
+       if (!verbose)
+               DaemonMode ();
+/*
+ * Catch signals to manage shutdown and
+ * refresh of interface address.
+ */
+       signal (SIGTERM, InitiateShutdown);
+       signal (SIGHUP, RefreshAddr);
+/*
+ * Set alias address if it has been given.
+ */
+       if (aliasAddr.s_addr != INADDR_NONE)
+               PacketAliasSetAddress (aliasAddr);
+/*
+ * We need largest descriptor number for select.
+ */
+
+       fdMax = -1;
+
+       if (divertIn > fdMax)
+               fdMax = divertIn;
+
+       if (divertOut > fdMax)
+               fdMax = divertOut;
+
+       if (divertInOut > fdMax)
+               fdMax = divertInOut;
+
+       if (routeSock > fdMax)
+               fdMax = routeSock;
+
+       while (running) {
+
+               if (divertInOut != -1 && !ifName && packetSock == -1) {
+/*
+ * When using only one socket, just call 
+ * DoAliasing repeatedly to process packets.
+ */
+                       DoAliasing (divertInOut, DONT_KNOW);
+                       continue;
+               }
+/* 
+ * Build read mask from socket descriptors to select.
+ */
+               FD_ZERO (&readMask);
+               FD_ZERO (&writeMask);
+
+/*
+ * If there is unsent packet in buffer, use select
+ * to check when socket comes writable again.
+ */
+               if (packetSock != -1) {
+
+                       FD_SET (packetSock, &writeMask);
+               }
+               else {
+/*
+ * No unsent packet exists - safe to check if
+ * new ones are available.
+ */
+                       if (divertIn != -1)
+                               FD_SET (divertIn, &readMask);
+
+                       if (divertOut != -1)
+                               FD_SET (divertOut, &readMask);
+
+                       if (divertInOut != -1)
+                               FD_SET (divertInOut, &readMask);
+               }
+/*
+ * Routing info is processed always.
+ */
+               if (routeSock != -1)
+                       FD_SET (routeSock, &readMask);
+
+               if (select (fdMax + 1,
+                           &readMask,
+                           &writeMask,
+                           NULL,
+                           NULL) == -1) {
+
+                       if (errno == EINTR)
+                               continue;
+
+                       Quit ("Select failed.");
+               }
+
+               if (packetSock != -1)
+                       if (FD_ISSET (packetSock, &writeMask))
+                               FlushPacketBuffer (packetSock);
+
+               if (divertIn != -1)
+                       if (FD_ISSET (divertIn, &readMask))
+                               DoAliasing (divertIn, INPUT);
+
+               if (divertOut != -1)
+                       if (FD_ISSET (divertOut, &readMask))
+                               DoAliasing (divertOut, OUTPUT);
+
+               if (divertInOut != -1) 
+                       if (FD_ISSET (divertInOut, &readMask))
+                               DoAliasing (divertInOut, DONT_KNOW);
+
+               if (routeSock != -1)
+                       if (FD_ISSET (routeSock, &readMask))
+                               HandleRoutingInfo (routeSock);
+       }
+
+       if (background)
+               unlink (PIDFILE);
+
+       return 0;
+}
+
+static void DaemonMode ()
+{
+       FILE*   pidFile;
+
+       daemon (0, 0);
+       background = 1;
+
+       pidFile = fopen (PIDFILE, "w");
+       if (pidFile) {
+
+               fprintf (pidFile, "%d\n", getpid ());
+               fclose (pidFile);
+       }
+}
+
+static void ParseArgs (int argc, char** argv)
+{
+       int             arg;
+       char*           parm;
+       char*           opt;
+       char            parmBuf[256];
+
+       for (arg = 1; arg < argc; arg++) {
+
+               opt  = argv[arg];
+               if (*opt != '-') {
+
+                       warnx ("invalid option %s", opt);
+                       Usage ();
+               }
+
+               parm = NULL;
+               parmBuf[0] = '\0';
+
+               while (arg < argc - 1) {
+
+                       if (argv[arg + 1][0] == '-')
+                               break;
+
+                       if (parm)
+                               strcat (parmBuf, " ");
+
+                       ++arg;
+                       parm = parmBuf;
+                       strcat (parmBuf, argv[arg]);
+               }
+
+               ParseOption (opt + 1, parm, 1);
+       }
+}
+
+static void DoAliasing (int fd, int direction)
+{
+       int                     bytes;
+       int                     origBytes;
+       int                     status;
+       int                     addrSize;
+       struct ip*              ip;
+
+       if (assignAliasAddr) {
+
+               SetAliasAddressFromIfName (ifName);
+               assignAliasAddr = 0;
+       }
+/*
+ * Get packet from socket.
+ */
+       addrSize  = sizeof packetAddr;
+       origBytes = recvfrom (fd,
+                             packetBuf,
+                             sizeof packetBuf,
+                             0,
+                             (struct sockaddr*) &packetAddr,
+                             &addrSize);
+
+       if (origBytes == -1) {
+
+               if (errno != EINTR)
+                       Warn ("read from divert socket failed");
+
+               return;
+       }
+/*
+ * This is a IP packet.
+ */
+       ip = (struct ip*) packetBuf;
+       if (direction == DONT_KNOW)
+               if (packetAddr.sin_addr.s_addr == INADDR_ANY)
+                       direction = OUTPUT;
+               else
+                       direction = INPUT;
+
+       if (verbose) {
+               
+/*
+ * Print packet direction and protocol type.
+ */
+               printf (direction == OUTPUT ? "Out " : "In  ");
+
+               switch (ip->ip_p) {
+               case IPPROTO_TCP:
+                       printf ("[TCP]  ");
+                       break;
+
+               case IPPROTO_UDP:
+                       printf ("[UDP]  ");
+                       break;
+
+               case IPPROTO_ICMP:
+                       printf ("[ICMP] ");
+                       break;
+
+               default:
+                       printf ("[%d]    ", ip->ip_p);
+                       break;
+               }
+/*
+ * Print addresses.
+ */
+               PrintPacket (ip);
+       }
+
+       if (direction == OUTPUT) {
+/*
+ * Outgoing packets. Do aliasing.
+ */
+               PacketAliasOut (packetBuf, IP_MAXPACKET);
+       }
+       else {
+
+/*
+ * Do aliasing.
+ */    
+               status = PacketAliasIn (packetBuf, IP_MAXPACKET);
+               if (status == PKT_ALIAS_IGNORED &&
+                   dropIgnoredIncoming) {
+
+                       if (verbose)
+                               printf (" dropped.\n");
+
+                       if (logDropped)
+                               SyslogPacket (ip, LOG_WARNING, "denied");
+
+                       return;
+               }
+       }
+/*
+ * Length might have changed during aliasing.
+ */
+       bytes = ntohs (ip->ip_len);
+/*
+ * Update alias overhead size for outgoing packets.
+ */
+       if (direction == OUTPUT &&
+           bytes - origBytes > aliasOverhead)
+               aliasOverhead = bytes - origBytes;
+
+       if (verbose) {
+               
+/*
+ * Print addresses after aliasing.
+ */
+               printf (" aliased to\n");
+               printf ("           ");
+               PrintPacket (ip);
+               printf ("\n");
+       }
+
+       packetLen       = bytes;
+       packetSock      = fd;
+       packetDirection = direction;
+
+       FlushPacketBuffer (fd);
+}
+
+static void FlushPacketBuffer (int fd)
+{
+       int                     wrote;
+       char                    msgBuf[80];
+/*
+ * Put packet back for processing.
+ */
+       wrote = sendto (fd, 
+                       packetBuf,
+                       packetLen,
+                       0,
+                       (struct sockaddr*) &packetAddr,
+                       sizeof packetAddr);
+       
+       if (wrote != packetLen) {
+/*
+ * If buffer space is not available,
+ * just return. Main loop will take care of 
+ * retrying send when space becomes available.
+ */
+               if (errno == ENOBUFS)
+                       return;
+
+               if (errno == EMSGSIZE) {
+
+                       if (packetDirection == OUTPUT &&
+                           ifMTU != -1)
+                               SendNeedFragIcmp (icmpSock,
+                                                 (struct ip*) packetBuf,
+                                                 ifMTU - aliasOverhead);
+               }
+               else {
+
+                       sprintf (msgBuf, "failed to write packet back");
+                       Warn (msgBuf);
+               }
+       }
+
+       packetSock = -1;
+}
+
+static void HandleRoutingInfo (int fd)
+{
+       int                     bytes;
+       struct if_msghdr        ifMsg;
+/*
+ * Get packet from socket.
+ */
+       bytes = read (fd, &ifMsg, sizeof ifMsg);
+       if (bytes == -1) {
+
+               Warn ("read from routing socket failed");
+               return;
+       }
+
+       if (ifMsg.ifm_version != RTM_VERSION) {
+
+               Warn ("unexpected packet read from routing socket");
+               return;
+       }
+
+       if (verbose)
+               printf ("Routing message %X received.\n", ifMsg.ifm_type);
+
+       if (ifMsg.ifm_type != RTM_NEWADDR)
+               return;
+
+       if (verbose && ifMsg.ifm_index == ifIndex)
+               printf ("Interface address has changed.\n");
+
+       if (ifMsg.ifm_index == ifIndex)
+               assignAliasAddr = 1;
+}
+
+static void PrintPacket (struct ip* ip)
+{
+       printf ("%s", FormatPacket (ip));
+}
+
+static void SyslogPacket (struct ip* ip, int priority, const char *label)
+{
+       syslog (priority, "%s %s", label, FormatPacket (ip));
+}
+
+static char* FormatPacket (struct ip* ip)
+{
+       static char     buf[256];
+       struct tcphdr*  tcphdr;
+       struct udphdr*  udphdr;
+       struct icmp*    icmphdr;
+       char            src[20];
+       char            dst[20];
+
+       strcpy (src, inet_ntoa (ip->ip_src));
+       strcpy (dst, inet_ntoa (ip->ip_dst));
+
+       switch (ip->ip_p) {
+       case IPPROTO_TCP:
+               tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
+               sprintf (buf, "[TCP] %s:%d -> %s:%d",
+                             src,
+                             ntohs (tcphdr->th_sport),
+                             dst,
+                             ntohs (tcphdr->th_dport));
+               break;
+
+       case IPPROTO_UDP:
+               udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
+               sprintf (buf, "[UDP] %s:%d -> %s:%d",
+                             src,
+                             ntohs (udphdr->uh_sport),
+                             dst,
+                             ntohs (udphdr->uh_dport));
+               break;
+
+       case IPPROTO_ICMP:
+               icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
+               sprintf (buf, "[ICMP] %s -> %s %u(%u)",
+                             src,
+                             dst,
+                             icmphdr->icmp_type,
+                             icmphdr->icmp_code);
+               break;
+
+       default:
+               sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst);
+               break;
+       }
+
+       return buf;
+}
+
+static void SetAliasAddressFromIfName (char* ifn)
+{
+       struct ifconf           cf;
+       struct ifreq            buf[32];
+       char                    msg[80];
+       struct ifreq*           ifPtr;
+       int                     extra;
+       int                     helperSock;
+       int                     bytes;
+       struct sockaddr_in*     addr;
+       int                     found;
+       struct ifreq            req;
+       char                    last[10];
+/*
+ * Create a dummy socket to access interface information.
+ */
+       helperSock = socket (AF_INET, SOCK_DGRAM, 0);
+       if (helperSock == -1) {
+
+               Quit ("Failed to create helper socket.");
+               exit (1);
+       }
+
+       cf.ifc_len = sizeof (buf);
+       cf.ifc_req = buf;
+/*
+ * Get interface data.
+ */
+       if (ioctl (helperSock, SIOCGIFCONF, &cf) == -1) {
+
+               Quit ("Ioctl SIOCGIFCONF failed.");
+               exit (1);
+       }
+
+       ifIndex = 0;
+       ifPtr   = buf;
+       bytes   = cf.ifc_len;
+       found   = 0;
+       last[0] = '\0';
+/*
+ * Loop through interfaces until one with
+ * given name is found. This is done to
+ * find correct interface index for routing
+ * message processing.
+ */
+       while (bytes) {
+
+               if (ifPtr->ifr_addr.sa_family == AF_INET &&
+                    !strcmp (ifPtr->ifr_name, ifn)) {
+
+                       found = 1;
+                       break;
+               }
+
+               if (strcmp (last, ifPtr->ifr_name)) {
+
+                       strcpy (last, ifPtr->ifr_name);
+                       ++ifIndex;
+               }
+
+               extra = ifPtr->ifr_addr.sa_len - sizeof (struct sockaddr);
+
+               ifPtr++;
+               ifPtr = (struct ifreq*) ((char*) ifPtr + extra);
+               bytes -= sizeof (struct ifreq) + extra;
+       }
+
+       if (!found) {
+
+               close (helperSock);
+               sprintf (msg, "Unknown interface name %s.\n", ifn);
+               Quit (msg);
+       }
+/*
+ * Get MTU size.
+ */
+       strcpy (req.ifr_name, ifn);
+
+       if (ioctl (helperSock, SIOCGIFMTU, &req) == -1)
+               Quit ("Cannot get interface mtu size.");
+
+       ifMTU = req.ifr_mtu;
+/*
+ * Get interface address.
+ */
+       if (ioctl (helperSock, SIOCGIFADDR, &req) == -1)
+               Quit ("Cannot get interface address.");
+
+       addr = (struct sockaddr_in*) &req.ifr_addr;
+       PacketAliasSetAddress (addr->sin_addr);
+       syslog (LOG_INFO, "Aliasing to %s, mtu %d bytes",
+                         inet_ntoa (addr->sin_addr),
+                         ifMTU);
+
+       close (helperSock);
+}
+
+void Quit (const char* msg)
+{
+       Warn (msg);
+       exit (1);
+}
+
+void Warn (const char* msg)
+{
+       if (background)
+               syslog (LOG_ALERT, "%s (%m)", msg);
+       else
+               warn (msg);
+}
+
+static void RefreshAddr (int sig)
+{
+       signal (SIGHUP, RefreshAddr);
+       if (ifName)
+               assignAliasAddr = 1;
+}
+
+static void InitiateShutdown (int sig)
+{
+/*
+ * Start timer to allow kernel gracefully
+ * shutdown existing connections when system
+ * is shut down.
+ */
+       signal (SIGALRM, Shutdown);
+       alarm (10);
+}
+
+static void Shutdown (int sig)
+{
+       running = 0;
+}
+
+/* 
+ * Different options recognized by this program.
+ */
+
+enum Option {
+
+       PacketAliasOption,
+       Verbose,
+       InPort,
+       OutPort,
+       Port,
+       AliasAddress,
+       InterfaceName,
+       RedirectPort,
+       RedirectAddress,
+       ConfigFile,
+       DynamicMode,
+       PptpAlias,
+       ProxyRule,
+       LogDenied,
+       LogFacility
+};
+
+enum Param {
+       
+       YesNo,
+       Numeric,
+       String,
+       None,
+       Address,
+       Service
+};
+
+/*
+ * Option information structure (used by ParseOption).
+ */
+
+struct OptionInfo {
+       
+       enum Option             type;
+       int                     packetAliasOpt;
+       enum Param              parm;
+       const char*             parmDescription;
+       const char*             description;
+       const char*             name; 
+       const char*             shortName;
+};
+
+/*
+ * Table of known options.
+ */
+
+static struct OptionInfo optionTable[] = {
+
+       { PacketAliasOption,
+               PKT_ALIAS_UNREGISTERED_ONLY,
+               YesNo,
+               "[yes|no]",
+               "alias only unregistered addresses",
+               "unregistered_only",
+               "u" },
+
+       { PacketAliasOption,
+               PKT_ALIAS_LOG,
+               YesNo,
+               "[yes|no]",
+               "enable logging",
+               "log",
+               "l" },
+
+       { PacketAliasOption,
+               PKT_ALIAS_PROXY_ONLY,
+               YesNo,
+               "[yes|no]",
+               "proxy only",
+               "proxy_only",
+               NULL },
+
+       { PacketAliasOption,
+               PKT_ALIAS_REVERSE,
+               YesNo,
+               "[yes|no]",
+               "operate in reverse mode",
+               "reverse",
+               NULL },
+
+       { PacketAliasOption,
+               PKT_ALIAS_DENY_INCOMING,
+               YesNo,
+               "[yes|no]",
+               "allow incoming connections",
+               "deny_incoming",
+               "d" },
+
+       { PacketAliasOption,
+               PKT_ALIAS_USE_SOCKETS,
+               YesNo,
+               "[yes|no]",
+               "use sockets to inhibit port conflict",
+               "use_sockets",
+               "s" },
+
+       { PacketAliasOption,
+               PKT_ALIAS_SAME_PORTS,
+               YesNo,
+               "[yes|no]",
+               "try to keep original port numbers for connections",
+               "same_ports",
+               "m" },
+
+       { Verbose,
+               0,
+               YesNo,
+               "[yes|no]",
+               "verbose mode, dump packet information",
+               "verbose",
+               "v" },
+       
+       { DynamicMode,
+               0,
+               YesNo,
+               "[yes|no]",
+               "dynamic mode, automatically detect interface address changes",
+               "dynamic",
+               NULL },
+       
+       { InPort,
+               0,
+               Service,
+               "number|service_name",
+               "set port for incoming packets",
+               "in_port",
+               "i" },
+       
+       { OutPort,
+               0,
+               Service,
+               "number|service_name",
+               "set port for outgoing packets",
+               "out_port",
+               "o" },
+       
+       { Port,
+               0,
+               Service,
+               "number|service_name",
+               "set port (defaults to natd/divert)",
+               "port",
+               "p" },
+       
+       { AliasAddress,
+               0,
+               Address,
+               "x.x.x.x",
+               "address to use for aliasing",
+               "alias_address",
+               "a" },
+       
+       { InterfaceName,
+               0,
+               String,
+               "network_if_name",
+               "take aliasing address from interface",
+               "interface",
+               "n" },
+
+       { ProxyRule,
+               0,
+               String,
+               "[type encode_ip_hdr|encode_tcp_stream] port xxxx server "
+               "a.b.c.d:yyyy",
+               "add transparent proxying / destination NAT",
+               "proxy_rule",
+               NULL },
+
+       { RedirectPort,
+               0,
+               String,
+               "tcp|udp local_addr:local_port_range [public_addr:]public_port_range"
+               " [remote_addr[:remote_port_range]]",
+               "redirect a port (or ports) for incoming traffic",
+               "redirect_port",
+               NULL },
+
+       { RedirectAddress,
+               0,
+               String,
+               "local_addr public_addr",
+               "define mapping between local and public addresses",
+               "redirect_address",
+               NULL },
+
+       { PptpAlias,
+               0,
+               String,
+               "src",
+               "define inside machine for PPTP traffic",
+               "pptpalias",
+               NULL },
+
+       { ConfigFile,
+               0,
+               String,
+               "file_name",
+               "read options from configuration file",
+               "config",
+               "f" },
+
+       { LogDenied,
+               0,
+               YesNo,
+               "[yes|no]",
+               "enable logging of denied incoming packets",
+               "log_denied",
+               NULL },
+
+       { LogFacility,
+               0,
+               String,
+               "facility",
+               "name of syslog facility to use for logging",
+               "log_facility",
+               NULL }
+
+};
+       
+static void ParseOption (const char* option, const char* parms, int cmdLine)
+{
+       int                     i;
+       struct OptionInfo*      info;
+       int                     yesNoValue;
+       int                     aliasValue;
+       int                     numValue;
+       u_short                 uNumValue;
+       const char*             strValue;
+       struct in_addr          addrValue;
+       int                     max;
+       char*                   end;
+       CODE*                   fac_record = NULL;
+/*
+ * Find option from table.
+ */
+       max = sizeof (optionTable) / sizeof (struct OptionInfo);
+       for (i = 0, info = optionTable; i < max; i++, info++) {
+
+               if (!strcmp (info->name, option))
+                       break;
+
+               if (info->shortName)
+                       if (!strcmp (info->shortName, option))
+                               break;
+       }
+
+       if (i >= max) {
+
+               warnx ("unknown option %s", option);
+               Usage ();
+       }
+
+       uNumValue       = 0;
+       yesNoValue      = 0;
+       numValue        = 0;
+       strValue        = NULL;
+/*
+ * Check parameters.
+ */
+       switch (info->parm) {
+       case YesNo:
+               if (!parms)
+                       parms = "yes";
+
+               if (!strcmp (parms, "yes"))
+                       yesNoValue = 1;
+               else
+                       if (!strcmp (parms, "no"))
+                               yesNoValue = 0;
+                       else
+                               errx (1, "%s needs yes/no parameter", option);
+               break;
+
+       case Service:
+               if (!parms)
+                       errx (1, "%s needs service name or "
+                                "port number parameter",
+                                option);
+
+               uNumValue = StrToPort (parms, "divert");
+               break;
+
+       case Numeric:
+               if (parms)
+                       numValue = strtol (parms, &end, 10);
+               else
+                       end = NULL;
+
+               if (end == parms)
+                       errx (1, "%s needs numeric parameter", option);
+               break;
+
+       case String:
+               strValue = parms;
+               if (!strValue)
+                       errx (1, "%s needs parameter", option);
+               break;
+
+       case None:
+               if (parms)
+                       errx (1, "%s does not take parameters", option);
+               break;
+
+       case Address:
+               if (!parms)
+                       errx (1, "%s needs address/host parameter", option);
+
+               StrToAddr (parms, &addrValue);
+               break;
+       }
+
+       switch (info->type) {
+       case PacketAliasOption:
+       
+               aliasValue = yesNoValue ? info->packetAliasOpt : 0;
+               PacketAliasSetMode (aliasValue, info->packetAliasOpt);
+               break;
+
+       case Verbose:
+               verbose = yesNoValue;
+               break;
+
+       case DynamicMode:
+               dynamicMode = yesNoValue;
+               break;
+
+       case InPort:
+               inPort = uNumValue;
+               break;
+
+       case OutPort:
+               outPort = uNumValue;
+               break;
+
+       case Port:
+               inOutPort = uNumValue;
+               break;
+
+       case AliasAddress:
+               memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr));
+               break;
+
+       case RedirectPort:
+               SetupPortRedirect (strValue);
+               break;
+
+       case RedirectAddress:
+               SetupAddressRedirect (strValue);
+               break;
+
+       case PptpAlias:
+               SetupPptpAlias (strValue);
+               break;
+
+       case ProxyRule:
+               PacketAliasProxyRule (strValue);
+               break;
+
+       case InterfaceName:
+               if (ifName)
+                       free (ifName);
+
+               ifName = strdup (strValue);
+               assignAliasAddr = 1;
+               break;
+
+       case ConfigFile:
+               ReadConfigFile (strValue);
+               break;
+
+       case LogDenied:
+               logDropped = 1;
+               break;
+
+       case LogFacility:
+
+               fac_record = facilitynames;
+               while (fac_record->c_name != NULL) {
+
+                       if (!strcmp (fac_record->c_name, strValue)) {
+
+                               logFacility = fac_record->c_val;
+                               break;
+
+                       }
+                       else
+                               fac_record++;
+               }
+
+               if(fac_record->c_name == NULL)
+                       errx(1, "Unknown log facility name: %s", strValue);     
+
+               break;
+       }
+}
+
+void ReadConfigFile (const char* fileName)
+{
+       FILE*   file;
+       char    buf[128];
+       char*   ptr;
+       char*   option;
+
+       file = fopen (fileName, "r");
+       if (!file) {
+
+               sprintf (buf, "Cannot open config file %s.\n", fileName);
+               Quit (buf);
+       }
+
+       while (fgets (buf, sizeof (buf), file)) {
+
+               ptr = strchr (buf, '\n');
+               if (!ptr)
+                       errx (1, "config line too long: %s", buf);
+
+               *ptr = '\0';
+               if (buf[0] == '#')
+                       continue;
+
+               ptr = buf;
+/*
+ * Skip white space at beginning of line.
+ */
+               while (*ptr && isspace (*ptr))
+                       ++ptr;
+
+               if (*ptr == '\0')
+                       continue;
+/*
+ * Extract option name.
+ */
+               option = ptr;
+               while (*ptr && !isspace (*ptr))
+                       ++ptr;
+
+               if (*ptr != '\0') {
+
+                       *ptr = '\0';
+                       ++ptr;
+               }
+/*
+ * Skip white space between name and parms.
+ */
+               while (*ptr && isspace (*ptr))
+                       ++ptr;
+
+               ParseOption (option, *ptr ? ptr : NULL, 0);
+       }
+
+       fclose (file);
+}
+
+static void Usage ()
+{
+       int                     i;
+       int                     max;
+       struct OptionInfo*      info;
+
+       fprintf (stderr, "Recognized options:\n\n");
+
+       max = sizeof (optionTable) / sizeof (struct OptionInfo);
+       for (i = 0, info = optionTable; i < max; i++, info++) {
+
+               fprintf (stderr, "-%-20s %s\n", info->name,
+                                               info->parmDescription);
+
+               if (info->shortName)
+                       fprintf (stderr, "-%-20s %s\n", info->shortName,
+                                                       info->parmDescription);
+
+               fprintf (stderr, "      %s\n\n", info->description);
+       }
+
+       exit (1);
+}
+
+void SetupPptpAlias (const char* parms)
+{
+       char            buf[128];
+       char*           ptr;
+       struct in_addr  srcAddr;
+
+       strcpy (buf, parms);
+
+/*
+ * Extract source address.
+ */
+       ptr = strtok (buf, " \t");
+       if (!ptr)
+               errx(1, "pptpalias: missing src address");
+
+       StrToAddr (ptr, &srcAddr);
+       PacketAliasPptp (srcAddr);
+}
+
+void SetupPortRedirect (const char* parms)
+{
+       char            buf[128];
+       char*           ptr;
+       struct in_addr  localAddr;
+       struct in_addr  publicAddr;
+       struct in_addr  remoteAddr;
+       port_range      portRange;
+       u_short         localPort      = 0;
+       u_short         publicPort     = 0;
+       u_short         remotePort     = 0;
+       u_short         numLocalPorts  = 0;
+       u_short         numPublicPorts = 0;
+       u_short         numRemotePorts = 0;
+       int             proto;
+       char*           protoName;
+       char*           separator;
+       int             i;
+
+       strcpy (buf, parms);
+/*
+ * Extract protocol.
+ */
+       protoName = strtok (buf, " \t");
+       if (!protoName)
+               errx (1, "redirect_port: missing protocol");
+
+       proto = StrToProto (protoName);
+/*
+ * Extract local address.
+ */
+       ptr = strtok (NULL, " \t");
+       if (!ptr)
+               errx (1, "redirect_port: missing local address");
+
+       if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 )
+               errx (1, "redirect_port: invalid local port range");
+
+       localPort     = GETLOPORT(portRange);
+       numLocalPorts = GETNUMPORTS(portRange);
+
+/*
+ * Extract public port and optinally address.
+ */
+       ptr = strtok (NULL, " \t");
+       if (!ptr)
+               errx (1, "redirect_port: missing public port");
+
+       separator = strchr (ptr, ':');
+       if (separator) {
+               if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 )
+                       errx (1, "redirect_port: invalid public port range");
+       }
+       else {
+               publicAddr.s_addr = INADDR_ANY;
+               if (StrToPortRange (ptr, protoName, &portRange) != 0)
+                       errx (1, "redirect_port: invalid public port range");
+       }
+
+       publicPort     = GETLOPORT(portRange);
+       numPublicPorts = GETNUMPORTS(portRange);
+
+/*
+ * Extract remote address and optionally port.
+ */
+       ptr = strtok (NULL, " \t");
+       if (ptr) {
+               separator = strchr (ptr, ':');
+               if (separator)
+                       if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0)
+                               errx (1, "redirect_port: invalid remote port range");
+               else {
+                       SETLOPORT(portRange, 0);
+                       SETNUMPORTS(portRange, 1);
+                       StrToAddr (ptr, &remoteAddr);
+               }
+       }
+       else {
+               SETLOPORT(portRange, 0);
+               SETNUMPORTS(portRange, 1);
+               remoteAddr.s_addr = INADDR_ANY;
+       }
+
+       remotePort     = GETLOPORT(portRange);
+       numRemotePorts = GETNUMPORTS(portRange);
+
+/*
+ * Make sure port ranges match up, then add the redirect ports.
+ */
+       if (numLocalPorts != numPublicPorts)
+               errx (1, "redirect_port: port ranges must be equal in size");
+
+       /* Remote port range is allowed to be '0' which means all ports. */
+       if (numRemotePorts != numLocalPorts && numRemotePorts != 1 && remotePort != 0)
+               errx (1, "redirect_port: remote port must be 0 or equal to local port range in size");
+
+       for (i = 0 ; i < numPublicPorts ; ++i) {
+               /* If remotePort is all ports, set it to 0. */
+               u_short remotePortCopy = remotePort + i;
+               if (numRemotePorts == 1 && remotePort == 0)
+                       remotePortCopy = 0;
+
+               PacketAliasRedirectPort (localAddr,
+                                        htons(localPort + i),
+                                        remoteAddr,
+                                        htons(remotePortCopy),
+                                        publicAddr,
+                                        htons(publicPort + i),
+                                        proto);
+       }
+}
+
+void SetupAddressRedirect (const char* parms)
+{
+       char            buf[128];
+       char*           ptr;
+       struct in_addr  localAddr;
+       struct in_addr  publicAddr;
+
+       strcpy (buf, parms);
+/*
+ * Extract local address.
+ */
+       ptr = strtok (buf, " \t");
+       if (!ptr)
+               errx (1, "redirect_address: missing local address");
+
+       StrToAddr (ptr, &localAddr);
+/*
+ * Extract public address.
+ */
+       ptr = strtok (NULL, " \t");
+       if (!ptr)
+               errx (1, "redirect_address: missing public address");
+
+       StrToAddr (ptr, &publicAddr);
+       PacketAliasRedirectAddr (localAddr, publicAddr);
+}
+
+void StrToAddr (const char* str, struct in_addr* addr)
+{
+       struct hostent* hp;
+
+       if (inet_aton (str, addr))
+               return;
+
+       hp = gethostbyname (str);
+       if (!hp)
+               errx (1, "unknown host %s", str);
+
+       memcpy (addr, hp->h_addr, sizeof (struct in_addr));
+}
+
+u_short StrToPort (const char* str, const char* proto)
+{
+       u_short         port;
+       struct servent* sp;
+       char*           end;
+
+       port = strtol (str, &end, 10);
+       if (end != str)
+               return htons (port);
+
+       sp = getservbyname (str, proto);
+       if (!sp)
+               errx (1, "unknown service %s/%s", str, proto);
+
+       return sp->s_port;
+}
+
+int StrToPortRange (const char* str, const char* proto, port_range *portRange)
+{
+       char*           sep;
+       struct servent* sp;
+       char*           end;
+       u_short         loPort;
+       u_short         hiPort;
+       
+       /* First see if this is a service, return corresponding port if so. */
+       sp = getservbyname (str,proto);
+       if (sp) {
+               SETLOPORT(*portRange, ntohs(sp->s_port));
+               SETNUMPORTS(*portRange, 1);
+               return 0;
+       }
+               
+       /* Not a service, see if it's a single port or port range. */
+       sep = strchr (str, '-');
+       if (sep == NULL) {
+               SETLOPORT(*portRange, strtol(str, &end, 10));
+               if (end != str) {
+                       /* Single port. */
+                       SETNUMPORTS(*portRange, 1);
+                       return 0;
+               }
+
+               /* Error in port range field. */
+               errx (1, "unknown service %s/%s", str, proto);
+       }
+
+       /* Port range, get the values and sanity check. */
+       sscanf (str, "%hu-%hu", &loPort, &hiPort);
+       SETLOPORT(*portRange, loPort);
+       SETNUMPORTS(*portRange, 0);     /* Error by default */
+       if (loPort <= hiPort)
+               SETNUMPORTS(*portRange, hiPort - loPort + 1);
+
+       if (GETNUMPORTS(*portRange) == 0)
+               errx (1, "invalid port range %s", str);
+
+       return 0;
+}
+
+
+int StrToProto (const char* str)
+{
+       if (!strcmp (str, "tcp"))
+               return IPPROTO_TCP;
+
+       if (!strcmp (str, "udp"))
+               return IPPROTO_UDP;
+
+       errx (1, "unknown protocol %s. Expected tcp or udp", str);
+}
+
+int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange)
+{
+       char*   ptr;
+
+       ptr = strchr (str, ':');
+       if (!ptr)
+               errx (1, "%s is missing port number", str);
+
+       *ptr = '\0';
+       ++ptr;
+
+       StrToAddr (str, addr);
+       return StrToPortRange (ptr, proto, portRange);
+}
diff --git a/natd.tproj/natd.h b/natd.tproj/natd.h
new file mode 100644 (file)
index 0000000..f179cb5
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * natd - Network Address Translation Daemon for FreeBSD.
+ *
+ * This software is provided free of charge, with no 
+ * warranty of any kind, either expressed or implied.
+ * Use at your own risk.
+ * 
+ * You may copy, modify and distribute this software (natd.h) freely.
+ *
+ * Ari Suutari <suutari@iki.fi>
+ *
+ *     $Id: natd.h,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $
+ */
+
+#define PIDFILE        "/var/run/natd.pid"
+#define        INPUT           1
+#define        OUTPUT          2
+#define        DONT_KNOW       3
+
+extern void Quit (const char* msg);
+extern void Warn (const char* msg);
+extern int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu);
+
+
diff --git a/netstat.tproj/DERIVED_FILES b/netstat.tproj/DERIVED_FILES
new file mode 100644 (file)
index 0000000..a4fa6c9
--- /dev/null
@@ -0,0 +1 @@
+unix/bsd/netiso/tp_astring.c
diff --git a/netstat.tproj/Makefile b/netstat.tproj/Makefile
new file mode 100644 (file)
index 0000000..a009e36
--- /dev/null
@@ -0,0 +1,54 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = netstat
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = netstat.h
+
+CFILES = data.c if.c inet.c iso.c main.c mbuf.c mroute.c route.c\
+         tp_astring.c unix.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble netstat.1\
+            DERIVED_FILES
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS =\
+               -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd/netat
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/netstat.tproj/Makefile.postamble b/netstat.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..34d448d
--- /dev/null
@@ -0,0 +1,2 @@
+INSTALL_AS_USER = root
+INSTALL_PERMISSIONS =4555
diff --git a/netstat.tproj/Makefile.preamble b/netstat.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..cc0d3d0
--- /dev/null
@@ -0,0 +1,4 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
+vpath %.c `pwd`
diff --git a/netstat.tproj/PB.project b/netstat.tproj/PB.project
new file mode 100644 (file)
index 0000000..91d9ed6
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        HEADERSEARCH = (
+            "$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd/netat"
+        ); 
+        H_FILES = (netstat.h); 
+        LIBRARYSEARCH = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (
+            data.c, 
+            if.c, 
+            inet.c, 
+            iso.c, 
+            main.c, 
+            mbuf.c, 
+            mroute.c, 
+            route.c, 
+            tp_astring.c, 
+            unix.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, netstat.1, DERIVED_FILES); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = netstat; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/netstat.tproj/data.c b/netstat.tproj/data.c
new file mode 100644 (file)
index 0000000..9e0bbe2
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* NeXT */
+#ifndef EXTERN
+#define EXTERN 
+#endif
+#include "netstat.h"
diff --git a/netstat.tproj/if.c b/netstat.tproj/if.c
new file mode 100644 (file)
index 0000000..43be850
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+/*
+static char sccsid[] = "@(#)if.c       8.3 (Berkeley) 4/28/95";
+*/
+static const char rcsid[] =
+       "$Id: if.c,v 1.1.1.2 2000/01/11 01:48:51 wsanchez Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+
+#ifdef IPX
+#include <netipx/ipx.h>
+#include <netipx/ipx_if.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+#ifdef ISO
+#include <netiso/iso.h>
+#include <netiso/iso_var.h>
+#endif
+#include <arpa/inet.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "netstat.h"
+
+#define        YES     1
+#define        NO      0
+
+static void sidewaysintpr __P((u_int, u_long));
+static void catchalarm __P((int));
+
+/*
+ * Print a description of the network interfaces.
+ */
+void
+intpr(interval, ifnetaddr)
+       int interval;
+       u_long ifnetaddr;
+{
+       struct ifnet ifnet;
+       struct ifnethead ifnethead;
+       union {
+               struct ifaddr ifa;
+               struct in_ifaddr in;
+#ifdef IPX
+               struct ipx_ifaddr ipx;
+#endif
+#ifdef NS
+               struct ns_ifaddr ns;
+#endif
+#ifdef ISO
+               struct iso_ifaddr iso;
+#endif
+       } ifaddr;
+       u_long ifaddraddr;
+       u_long ifaddrfound;
+       u_long ifnetfound;
+       struct sockaddr *sa;
+       char name[32], tname[16];
+
+       if (ifnetaddr == 0) {
+               printf("ifnet: symbol not defined\n");
+               return;
+       }
+       if (interval) {
+               sidewaysintpr((unsigned)interval, ifnetaddr);
+               return;
+       }
+       if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead))
+               return;
+       ifnetaddr = (u_long)ifnethead.tqh_first;
+       if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
+               return;
+
+       printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
+               "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
+       if (bflag)
+               printf(" %10.10s","Ibytes");
+       printf(" %8.8s %5.5s", "Opkts", "Oerrs");
+       if (bflag)
+               printf(" %10.10s","Obytes");
+       printf(" %5s", "Coll");
+       if (tflag)
+               printf(" %s", "Time");
+       if (dflag)
+               printf(" %s", "Drop");
+       putchar('\n');
+       ifaddraddr = 0;
+       while (ifnetaddr || ifaddraddr) {
+               struct sockaddr_in *sin;
+               register char *cp;
+               int n, m;
+
+               if (ifaddraddr == 0) {
+                       ifnetfound = ifnetaddr;
+                       if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
+                           kread((u_long)ifnet.if_name, tname, 16))
+                               return;
+                       tname[15] = '\0';
+                       ifnetaddr = (u_long)ifnet.if_link.tqe_next;
+                       snprintf(name, 32, "%s%d", tname, ifnet.if_unit);
+                       if (interface != 0 && (strcmp(name, interface) != 0))
+                               continue;
+                       cp = index(name, '\0');
+                       if ((ifnet.if_flags&IFF_UP) == 0)
+                               *cp++ = '*';
+                       *cp = '\0';
+                       ifaddraddr = (u_long)ifnet.if_addrhead.tqh_first;
+               }
+               printf("%-5.5s %-5lu ", name, ifnet.if_mtu);
+               ifaddrfound = ifaddraddr;
+               if (ifaddraddr == 0) {
+                       printf("%-13.13s ", "none");
+                       printf("%-15.15s ", "none");
+               } else {
+                       if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
+                               ifaddraddr = 0;
+                               continue;
+                       }
+#define CP(x) ((char *)(x))
+                       cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
+                               CP(&ifaddr); sa = (struct sockaddr *)cp;
+                       switch (sa->sa_family) {
+                       case AF_UNSPEC:
+                               printf("%-13.13s ", "none");
+                               printf("%-15.15s ", "none");
+                               break;
+                       case AF_INET:
+                               sin = (struct sockaddr_in *)sa;
+#ifdef notdef
+                               /* can't use inet_makeaddr because kernel
+                                * keeps nets unshifted.
+                                */
+                               in = inet_makeaddr(ifaddr.in.ia_subnet,
+                                       INADDR_ANY);
+                               printf("%-13.13s ", netname(in.s_addr,
+                                   ifaddr.in.ia_subnetmask));
+#else
+                               printf("%-13.13s ",
+                                   netname(htonl(ifaddr.in.ia_subnet),
+                                   ifaddr.in.ia_subnetmask));
+#endif
+                               printf("%-15.15s ",
+                                   routename(sin->sin_addr.s_addr));
+                               break;
+#ifdef IPX
+
+                       case AF_IPX:
+                               {
+                               struct sockaddr_ipx *sipx =
+                                       (struct sockaddr_ipx *)sa;
+                               u_long net;
+                               char netnum[10];
+
+                               *(union ipx_net *) &net = sipx->sipx_addr.x_net;
+                               sprintf(netnum, "%lx", (u_long)ntohl(net));
+                               printf("ipx:%-8s ", netnum);
+/*                             printf("ipx:%-8s ", netname(net, 0L)); */
+                               printf("%-15s ",
+                                   ipx_phost((struct sockaddr *)sipx));
+                               }
+                               break;
+#endif
+#if 0
+                       case AF_APPLETALK:
+                               printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
+                               printf("%-9.9s  ",atalk_print(sa,0x0b) );
+                               break;
+#endif
+#ifdef NS
+                       case AF_NS:
+                               {
+                               struct sockaddr_ns *sns =
+                                       (struct sockaddr_ns *)sa;
+                               u_long net;
+                               char netnum[10];
+
+                               *(union ns_net *) &net = sns->sns_addr.x_net;
+                               sprintf(netnum, "%lxH", ntohl(net));
+                               upHex(netnum);
+                               printf("ns:%-8s ", netnum);
+                               printf("%-15s ",
+                                   ns_phost((struct sockaddr *)sns));
+                               }
+                               break;
+#endif
+                       case AF_LINK:
+                               {
+                               struct sockaddr_dl *sdl =
+                                       (struct sockaddr_dl *)sa;
+                                   cp = (char *)LLADDR(sdl);
+                                   n = sdl->sdl_alen;
+                               }
+                               m = printf("%-11.11s ", "<Link>");
+                               goto hexprint;
+                       default:
+                               m = printf("(%d)", sa->sa_family);
+                               for (cp = sa->sa_len + (char *)sa;
+                                       --cp > sa->sa_data && (*cp == 0);) {}
+                               n = cp - sa->sa_data + 1;
+                               cp = sa->sa_data;
+                       hexprint:
+                               while (--n >= 0)
+                                       m += printf("%02x%c", *cp++ & 0xff,
+                                                   n > 0 ? '.' : ' ');
+                               m = 30 - m;
+                               while (m-- > 0)
+                                       putchar(' ');
+                               break;
+                       }
+                       ifaddraddr = (u_long)ifaddr.ifa.ifa_link.tqe_next;
+               }
+               printf("%8lu %5lu ",
+                   ifnet.if_ipackets, ifnet.if_ierrors);
+               if (bflag)
+                       printf("%10lu ", ifnet.if_ibytes);
+               printf("%8lu %5lu ",
+                   ifnet.if_opackets, ifnet.if_oerrors);
+               if (bflag)
+                       printf("%10lu ", ifnet.if_obytes);
+               printf("%5lu", ifnet.if_collisions);
+               if (tflag)
+                       printf(" %3d", ifnet.if_timer);
+               if (dflag)
+                       printf(" %3d", ifnet.if_snd.ifq_drops);
+               putchar('\n');
+               if (aflag && ifaddrfound) {
+                       /*
+                        * Print family's multicast addresses
+                        */
+                       u_long multiaddr;
+                       struct ifmultiaddr ifma;
+                       union {
+                               struct sockaddr sa;
+                               struct sockaddr_in in;
+                               struct sockaddr_dl dl;
+                       } msa;
+                       const char *fmt;
+
+                       for(multiaddr = (u_long)ifnet.if_multiaddrs.lh_first;
+                           multiaddr;
+                           multiaddr = (u_long)ifma.ifma_link.le_next) {
+                               if (kread(multiaddr, (char *)&ifma,
+                                         sizeof ifma))
+                                       break;
+                               if (kread((u_long)ifma.ifma_addr, (char *)&msa,
+                                         sizeof msa))
+                                       break;
+                               if (msa.sa.sa_family != sa->sa_family)
+                                       continue;
+                               
+                               fmt = 0;
+                               switch (msa.sa.sa_family) {
+                               case AF_INET:
+                                       fmt = routename(msa.in.sin_addr.s_addr);
+                                       break;
+
+                               case AF_LINK:
+                                       switch (ifnet.if_type) {
+                                       case IFT_ETHER:
+                                       case IFT_FDDI:
+                                               fmt = ether_ntoa(
+                                                       (struct ether_addr *)
+                                                       LLADDR(&msa.dl));
+                                               break;
+                                       }
+                                       break;
+                               }
+                               if (fmt)
+                                       printf("%23s %s\n", "", fmt);
+                       }
+               }
+       }
+}
+
+#define        MAXIF   10
+struct iftot {
+       char    ift_name[16];           /* interface name */
+       u_int   ift_ip;                 /* input packets */
+       u_int   ift_ie;                 /* input errors */
+       u_int   ift_op;                 /* output packets */
+       u_int   ift_oe;                 /* output errors */
+       u_int   ift_co;                 /* collisions */
+       u_int   ift_dr;                 /* drops */
+       u_int   ift_ib;                 /* input bytes */
+       u_int   ift_ob;                 /* output bytes */
+} iftot[MAXIF];
+
+u_char signalled;                      /* set if alarm goes off "early" */
+
+/*
+ * Print a running summary of interface statistics.
+ * Repeat display every interval seconds, showing statistics
+ * collected over that interval.  Assumes that interval is non-zero.
+ * First line printed at top of screen is always cumulative.
+ * XXX - should be rewritten to use ifmib(4).
+ */
+static void
+sidewaysintpr(interval, off)
+       unsigned interval;
+       u_long off;
+{
+       struct ifnet ifnet;
+       u_long firstifnet;
+       struct ifnethead ifnethead;
+       register struct iftot *ip, *total;
+       register int line;
+       struct iftot *lastif, *sum, *interesting;
+       int oldmask, first;
+       u_long interesting_off;
+
+       if (kread(off, (char *)&ifnethead, sizeof ifnethead))
+               return;
+       firstifnet = (u_long)ifnethead.tqh_first;
+
+       lastif = iftot;
+       sum = iftot + MAXIF - 1;
+       total = sum - 1;
+       interesting = NULL;
+       interesting_off = 0;
+       for (off = firstifnet, ip = iftot; off;) {
+               char name[16], tname[16];
+
+               if (kread(off, (char *)&ifnet, sizeof ifnet))
+                       break;
+               if (kread((u_long)ifnet.if_name, tname, 16))
+                       break;
+               tname[15] = '\0';
+               snprintf(name, 16, "%s%d", tname, ifnet.if_unit);
+               if (interface && strcmp(name, interface) == 0) {
+                       interesting = ip;
+                       interesting_off = off;
+               }
+               snprintf(ip->ift_name, 16, "(%s)", name);;
+               ip++;
+               if (ip >= iftot + MAXIF - 2)
+                       break;
+               off = (u_long) ifnet.if_link.tqe_next;
+       }
+       lastif = ip;
+
+       (void)signal(SIGALRM, catchalarm);
+       signalled = NO;
+       (void)alarm(interval);
+       for (ip = iftot; ip < iftot + MAXIF; ip++) {
+               ip->ift_ip = 0;
+               ip->ift_ie = 0;
+               ip->ift_ib = 0;
+               ip->ift_op = 0;
+               ip->ift_oe = 0;
+               ip->ift_ob = 0;
+               ip->ift_co = 0;
+               ip->ift_dr = 0;
+       }
+       first = 1;
+banner:
+       printf("%17s %14s %16s", "input",
+           interesting ? interesting->ift_name : "(Total)", "output");
+       putchar('\n');
+       printf("%10s %5s %10s %10s %5s %10s %5s",
+           "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
+       if (dflag)
+               printf(" %5.5s", "drops");
+       putchar('\n');
+       fflush(stdout);
+       line = 0;
+loop:
+       if (interesting != NULL) {
+               ip = interesting;
+               if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) {
+                       printf("???\n");
+                       exit(1);
+               };
+               if (!first) {
+                       printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu",
+                               ifnet.if_ipackets - ip->ift_ip,
+                               ifnet.if_ierrors - ip->ift_ie,
+                               ifnet.if_ibytes - ip->ift_ib,
+                               ifnet.if_opackets - ip->ift_op,
+                               ifnet.if_oerrors - ip->ift_oe,
+                               ifnet.if_obytes - ip->ift_ob,
+                               ifnet.if_collisions - ip->ift_co);
+                       if (dflag)
+                               printf(" %5u", ifnet.if_snd.ifq_drops - ip->ift_dr);
+               }
+               ip->ift_ip = ifnet.if_ipackets;
+               ip->ift_ie = ifnet.if_ierrors;
+               ip->ift_ib = ifnet.if_ibytes;
+               ip->ift_op = ifnet.if_opackets;
+               ip->ift_oe = ifnet.if_oerrors;
+               ip->ift_ob = ifnet.if_obytes;
+               ip->ift_co = ifnet.if_collisions;
+               ip->ift_dr = ifnet.if_snd.ifq_drops;
+       } else {
+               sum->ift_ip = 0;
+               sum->ift_ie = 0;
+               sum->ift_ib = 0;
+               sum->ift_op = 0;
+               sum->ift_oe = 0;
+               sum->ift_ob = 0;
+               sum->ift_co = 0;
+               sum->ift_dr = 0;
+               for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
+                       if (kread(off, (char *)&ifnet, sizeof ifnet)) {
+                               off = 0;
+                               continue;
+                       }
+                       sum->ift_ip += ifnet.if_ipackets;
+                       sum->ift_ie += ifnet.if_ierrors;
+                       sum->ift_ib += ifnet.if_ibytes;
+                       sum->ift_op += ifnet.if_opackets;
+                       sum->ift_oe += ifnet.if_oerrors;
+                       sum->ift_ob += ifnet.if_obytes;
+                       sum->ift_co += ifnet.if_collisions;
+                       sum->ift_dr += ifnet.if_snd.ifq_drops;
+                       off = (u_long) ifnet.if_link.tqe_next;
+               }
+               if (!first) {
+                       printf("%10u %5u %10u %10u %5u %10u %5u",
+                               sum->ift_ip - total->ift_ip,
+                               sum->ift_ie - total->ift_ie,
+                               sum->ift_ib - total->ift_ib,
+                               sum->ift_op - total->ift_op,
+                               sum->ift_oe - total->ift_oe,
+                               sum->ift_ob - total->ift_ob,
+                               sum->ift_co - total->ift_co);
+                       if (dflag)
+                               printf(" %5u", sum->ift_dr - total->ift_dr);
+               }
+               *total = *sum;
+       }
+       if (!first)
+               putchar('\n');
+       fflush(stdout);
+       oldmask = sigblock(sigmask(SIGALRM));
+       if (! signalled) {
+               sigpause(0);
+       }
+       sigsetmask(oldmask);
+       signalled = NO;
+       (void)alarm(interval);
+       line++;
+       first = 0;
+       if (line == 21)
+               goto banner;
+       else
+               goto loop;
+       /*NOTREACHED*/
+}
+
+/*
+ * Called if an interval expires before sidewaysintpr has completed a loop.
+ * Sets a flag to not wait for the alarm.
+ */
+static void
+catchalarm(signo)
+       int signo;
+{
+       signalled = YES;
+}
diff --git a/netstat.tproj/inet.c b/netstat.tproj/inet.c
new file mode 100644 (file)
index 0000000..0c2250a
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 1983, 1988, 1993, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+/*
+static char sccsid[] = "@(#)inet.c     8.5 (Berkeley) 5/24/95";
+*/
+static const char rcsid[] =
+       "$Id: inet.c,v 1.1.1.2 2000/01/11 01:48:52 wsanchez Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/protosw.h>
+
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+#include <netinet/igmp_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_seq.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcp_debug.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <arpa/inet.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+char   *inetname __P((struct in_addr *));
+void   inetprint __P((struct in_addr *, int, char *, int));
+
+/*
+ * Print a summary of connections related to an Internet
+ * protocol.  For TCP, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+void
+protopr(proto, name)
+       u_long proto;           /* for sysctl version we pass proto # */
+       char *name;
+{
+       int istcp;
+       static int first = 1;
+       char *buf;
+       const char *mibvar;
+       struct tcpcb *tp;
+       struct inpcb *inp;
+       struct xinpgen *xig, *oxig;
+       struct xsocket *so;
+       size_t len;
+
+       istcp = 0;
+       switch (proto) {
+       case IPPROTO_TCP:
+               istcp = 1;
+               mibvar = "net.inet.tcp.pcblist";
+               break;
+       case IPPROTO_UDP:
+               mibvar = "net.inet.udp.pcblist";
+               break;
+       case IPPROTO_DIVERT:
+               mibvar = "net.inet.divert.pcblist";
+               break;
+       default:
+               mibvar = "net.inet.raw.pcblist";
+               break;
+       }
+       len = 0;
+       if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+               if (errno != ENOENT)
+                       warn("sysctl: %s", mibvar);
+               return;
+       }
+       if ((buf = malloc(len)) == 0) {
+               warn("malloc %lu bytes", (u_long)len);
+               return;
+       }
+       if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+               warn("sysctl: %s", mibvar);
+               free(buf);
+               return;
+       }
+
+       oxig = xig = (struct xinpgen *)buf;
+       for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
+            xig->xig_len > sizeof(struct xinpgen);
+            xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
+               if (istcp) {
+                       tp = &((struct xtcpcb *)xig)->xt_tp;
+                       inp = &((struct xtcpcb *)xig)->xt_inp;
+                       so = &((struct xtcpcb *)xig)->xt_socket;
+               } else {
+                       inp = &((struct xinpcb *)xig)->xi_inp;
+                       so = &((struct xinpcb *)xig)->xi_socket;
+               }
+
+               /* Ignore sockets for protocols other than the desired one. */
+               if (so->xso_protocol != proto)
+                       continue;
+
+               /* Ignore PCBs which were freed during copyout. */
+               if (inp->inp_gencnt > oxig->xig_gen)
+                       continue;
+
+               if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
+                       continue;
+
+               if (first) {
+                       printf("Active Internet connections");
+                       if (aflag)
+                               printf(" (including servers)");
+                       putchar('\n');
+                       if (Aflag)
+                               printf("%-8.8s ", "Socket");
+                       printf(Aflag ?
+                               "%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
+                               "%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
+                               "Proto", "Recv-Q", "Send-Q",
+                               "Local Address", "Foreign Address", "(state)");
+                       first = 0;
+               }
+               if (Aflag) {
+                       if (istcp)
+                               printf("%8lx ", (u_long)inp->inp_ppcb);
+                       else
+                               printf("%8lx ", (u_long)so->so_pcb);
+               }
+               printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc,
+                       so->so_snd.sb_cc);
+               if (nflag) {
+                       inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+                           name, 1);
+                       inetprint(&inp->inp_faddr, (int)inp->inp_fport,
+                           name, 1);
+               } else if (inp->inp_flags & INP_ANONPORT) {
+                       inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+                           name, 1);
+                       inetprint(&inp->inp_faddr, (int)inp->inp_fport,
+                           name, 0);
+               } else {
+                       inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+                           name, 0);
+                       inetprint(&inp->inp_faddr, (int)inp->inp_fport,
+                           name, inp->inp_lport != inp->inp_fport);
+               }
+               if (istcp) {
+                       if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
+                               printf(" %d", tp->t_state);
+                      else {
+                               printf(" %s", tcpstates[tp->t_state]);
+#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
+                              /* Show T/TCP `hidden state' */
+                              if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
+                                      putchar('*');
+#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
+                      }
+               }
+               putchar('\n');
+       }
+       if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
+               if (oxig->xig_count > xig->xig_count) {
+                       printf("Some %s sockets may have been deleted.\n",
+                              name);
+               } else if (oxig->xig_count < xig->xig_count) {
+                       printf("Some %s sockets may have been created.\n",
+                              name);
+               } else {
+                       printf("Some %s sockets may have been created or deleted",
+                              name);
+               }
+       }
+       free(buf);
+}
+
+/*
+ * Dump TCP statistics structure.
+ */
+void
+tcp_stats(off, name)
+       u_long off;
+       char *name;
+{
+       struct tcpstat tcpstat;
+       size_t len = sizeof tcpstat;
+       
+       if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
+               warn("sysctl: net.inet.tcp.stats");
+               return;
+       }
+
+       printf ("%s:\n", name);
+
+#define        p(f, m) if (tcpstat.f || sflag <= 1) \
+    printf(m, tcpstat.f, plural(tcpstat.f))
+#define        p1a(f, m) if (tcpstat.f || sflag <= 1) \
+    printf(m, tcpstat.f)
+#define        p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
+    printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
+#define        p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
+    printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
+#define        p3(f, m) if (tcpstat.f || sflag <= 1) \
+    printf(m, tcpstat.f, plurales(tcpstat.f))
+
+       p(tcps_sndtotal, "\t%lu packet%s sent\n");
+       p2(tcps_sndpack,tcps_sndbyte,
+               "\t\t%lu data packet%s (%lu byte%s)\n");
+       p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
+               "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
+       p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
+       p2a(tcps_sndacks, tcps_delack,
+               "\t\t%lu ack-only packet%s (%lu delayed)\n");
+       p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
+       p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
+       p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
+       p(tcps_sndctrl, "\t\t%lu control packet%s\n");
+       p(tcps_rcvtotal, "\t%lu packet%s received\n");
+       p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
+       p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
+       p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
+       p2(tcps_rcvpack, tcps_rcvbyte,
+               "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
+       p2(tcps_rcvduppack, tcps_rcvdupbyte,
+               "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
+       p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
+       p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
+               "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
+       p2(tcps_rcvoopack, tcps_rcvoobyte,
+               "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
+       p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
+               "\t\t%lu packet%s (%lu byte%s) of data after window\n");
+       p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
+       p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
+       p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
+       p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
+       p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
+       p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
+       p(tcps_connattempt, "\t%lu connection request%s\n");
+       p(tcps_accepts, "\t%lu connection accept%s\n");
+       p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
+       p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
+       p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
+       p2(tcps_closed, tcps_drops,
+               "\t%lu connection%s closed (including %lu drop%s)\n");
+       p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
+       p(tcps_cachedrttvar, 
+         "\t\t%lu connection%s updated cached RTT variance on close\n");
+       p(tcps_cachedssthresh,
+         "\t\t%lu connection%s updated cached ssthresh on close\n");
+       p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
+       p2(tcps_rttupdated, tcps_segstimed,
+               "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
+       p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
+       p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
+       p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
+       p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
+       p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
+       p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
+       p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
+       p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
+       p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
+#undef p
+#undef p1a
+#undef p2
+#undef p2a
+#undef p3
+}
+
+/*
+ * Dump UDP statistics structure.
+ */
+void
+udp_stats(off, name)
+       u_long off;
+       char *name;
+{
+       struct udpstat udpstat;
+       size_t len = sizeof udpstat;
+       u_long delivered;
+
+       if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
+               warn("sysctl: net.inet.udp.stats");
+               return;
+       }
+
+       printf("%s:\n", name);
+#define        p(f, m) if (udpstat.f || sflag <= 1) \
+    printf(m, udpstat.f, plural(udpstat.f))
+#define        p1a(f, m) if (udpstat.f || sflag <= 1) \
+    printf(m, udpstat.f)
+       p(udps_ipackets, "\t%lu datagram%s received\n");
+       p1a(udps_hdrops, "\t%lu with incomplete header\n");
+       p1a(udps_badlen, "\t%lu with bad data length field\n");
+       p1a(udps_badsum, "\t%lu with bad checksum\n");
+       p1a(udps_noport, "\t%lu dropped due to no socket\n");
+       p(udps_noportbcast,
+           "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
+       p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
+       p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
+       delivered = udpstat.udps_ipackets -
+                   udpstat.udps_hdrops -
+                   udpstat.udps_badlen -
+                   udpstat.udps_badsum -
+                   udpstat.udps_noport -
+                   udpstat.udps_noportbcast -
+                   udpstat.udps_fullsock;
+       if (delivered || sflag <= 1)
+               printf("\t%lu delivered\n", delivered);
+       p(udps_opackets, "\t%lu datagram%s output\n");
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump IP statistics structure.
+ */
+void
+ip_stats(off, name)
+       u_long off;
+       char *name;
+{
+       struct ipstat ipstat;
+       size_t len = sizeof ipstat;
+
+       if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) {
+               warn("sysctl: net.inet.ip.stats");
+               return;
+       }
+
+       printf("%s:\n", name);
+
+#define        p(f, m) if (ipstat.f || sflag <= 1) \
+    printf(m, ipstat.f, plural(ipstat.f))
+#define        p1a(f, m) if (ipstat.f || sflag <= 1) \
+    printf(m, ipstat.f)
+
+       p(ips_total, "\t%lu total packet%s received\n");
+       p(ips_badsum, "\t%lu bad header checksum%s\n");
+       p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
+       p1a(ips_tooshort, "\t%lu with data size < data length\n");
+       p1a(ips_badhlen, "\t%lu with header length < data size\n");
+       p1a(ips_badlen, "\t%lu with data length < header length\n");
+       p1a(ips_badoptions, "\t%lu with bad options\n");
+       p1a(ips_badvers, "\t%lu with incorrect version number\n");
+       p(ips_fragments, "\t%lu fragment%s received\n");
+       p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
+       p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
+       p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
+       p(ips_delivered, "\t%lu packet%s for this host\n");
+       p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
+       p(ips_forward, "\t%lu packet%s forwarded");
+       p(ips_fastforward, " (%lu packet%s fast forwarded)");
+       if (ipstat.ips_forward || sflag <= 1) 
+               putchar('\n');
+       p(ips_cantforward, "\t%lu packet%s not forwardable\n");
+       p(ips_notmember,
+         "\t%lu packet%s received for unknown multicast group\n");
+       p(ips_redirectsent, "\t%lu redirect%s sent\n");
+       p(ips_localout, "\t%lu packet%s sent from this host\n");
+       p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
+       p(ips_odropped,
+         "\t%lu output packet%s dropped due to no bufs, etc.\n");
+       p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
+       p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
+       p(ips_ofragments, "\t%lu fragment%s created\n");
+       p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
+#undef p
+#undef p1a
+}
+
+static char *icmpnames[] = {
+       "echo reply",
+       "#1",
+       "#2",
+       "destination unreachable",
+       "source quench",
+       "routing redirect",
+       "#6",
+       "#7",
+       "echo",
+       "router advertisement",
+       "router solicitation",
+       "time exceeded",
+       "parameter problem",
+       "time stamp",
+       "time stamp reply",
+       "information request",
+       "information request reply",
+       "address mask request",
+       "address mask reply",
+};
+
+/*
+ * Dump ICMP statistics.
+ */
+void
+icmp_stats(off, name)
+       u_long off;
+       char *name;
+{
+       struct icmpstat icmpstat;
+       int i, first;
+       int mib[4];             /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
+       size_t len;
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_INET;
+       mib[2] = IPPROTO_ICMP;
+       mib[3] = ICMPCTL_STATS;
+
+       len = sizeof icmpstat;
+       memset(&icmpstat, 0, len);
+       if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0)
+               return;         /* XXX should complain, but not traditional */
+
+       printf("%s:\n", name);
+
+#define        p(f, m) if (icmpstat.f || sflag <= 1) \
+    printf(m, icmpstat.f, plural(icmpstat.f))
+#define        p1a(f, m) if (icmpstat.f || sflag <= 1) \
+    printf(m, icmpstat.f)
+
+       p(icps_error, "\t%lu call%s to icmp_error\n");
+       p(icps_oldicmp,
+           "\t%lu error%s not generated 'cuz old message was icmp\n");
+       for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+               if (icmpstat.icps_outhist[i] != 0) {
+                       if (first) {
+                               printf("\tOutput histogram:\n");
+                               first = 0;
+                       }
+                       printf("\t\t%s: %lu\n", icmpnames[i],
+                               icmpstat.icps_outhist[i]);
+               }
+       p(icps_badcode, "\t%lu message%s with bad code fields\n");
+       p(icps_tooshort, "\t%lu message%s < minimum length\n");
+       p(icps_checksum, "\t%lu bad checksum%s\n");
+       p(icps_badlen, "\t%lu message%s with bad length\n");
+       p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
+       p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
+       for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+               if (icmpstat.icps_inhist[i] != 0) {
+                       if (first) {
+                               printf("\tInput histogram:\n");
+                               first = 0;
+                       }
+                       printf("\t\t%s: %lu\n", icmpnames[i],
+                               icmpstat.icps_inhist[i]);
+               }
+       p(icps_reflect, "\t%lu message response%s generated\n");
+#undef p
+#undef p1a
+       mib[3] = ICMPCTL_MASKREPL;
+       len = sizeof i;
+       if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
+               return;
+       printf("\tICMP address mask responses are %sabled\n", 
+              i ? "en" : "dis");
+}
+
+/*
+ * Dump IGMP statistics structure.
+ */
+void
+igmp_stats(off, name)
+       u_long off;
+       char *name;
+{
+       struct igmpstat igmpstat;
+       size_t len = sizeof igmpstat;
+
+       if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) {
+               warn("sysctl: net.inet.igmp.stats");
+               return;
+       }
+
+       printf("%s:\n", name);
+
+#define        p(f, m) if (igmpstat.f || sflag <= 1) \
+    printf(m, igmpstat.f, plural(igmpstat.f))
+#define        py(f, m) if (igmpstat.f || sflag <= 1) \
+    printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
+       p(igps_rcv_total, "\t%u message%s received\n");
+        p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
+        p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
+        py(igps_rcv_queries, "\t%u membership quer%s received\n");
+        py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
+        p(igps_rcv_reports, "\t%u membership report%s received\n");
+        p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
+        p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
+        p(igps_snd_reports, "\t%u membership report%s sent\n");
+#undef p
+#undef py
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ */
+void
+inetprint(in, port, proto,numeric)
+       register struct in_addr *in;
+       int port;
+       char *proto;
+       int numeric;
+{
+       struct servent *sp = 0;
+       char line[80], *cp;
+       int width;
+
+       sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in));
+       cp = index(line, '\0');
+       if (!numeric && port)
+               sp = getservbyport((int)port, proto);
+       if (sp || port == 0)
+               sprintf(cp, "%.15s", sp ? sp->s_name : "*");
+       else
+               sprintf(cp, "%d", ntohs((u_short)port));
+       width = Aflag ? 18 : 22;
+       printf(" %-*.*s", width, width, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If the nflag has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+char *
+inetname(inp)
+       struct in_addr *inp;
+{
+       register char *cp;
+       static char line[MAXHOSTNAMELEN + 1];
+       struct hostent *hp;
+       struct netent *np;
+
+       cp = 0;
+       if (!nflag && inp->s_addr != INADDR_ANY) {
+               int net = inet_netof(*inp);
+               int lna = inet_lnaof(*inp);
+
+               if (lna == INADDR_ANY) {
+                       np = getnetbyaddr(net, AF_INET);
+                       if (np)
+                               cp = np->n_name;
+               }
+               if (cp == 0) {
+                       hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
+                       if (hp) {
+                               cp = hp->h_name;
+                               trimdomain(cp);
+                       }
+               }
+       }
+       if (inp->s_addr == INADDR_ANY)
+               strcpy(line, "*");
+       else if (cp) {
+               strncpy(line, cp, sizeof(line) - 1);
+               line[sizeof(line) - 1] = '\0';
+       } else {
+               inp->s_addr = ntohl(inp->s_addr);
+#define C(x)   ((u_int)((x) & 0xff))
+               sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
+                   C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
+       }
+       return (line);
+}
diff --git a/netstat.tproj/iso.c b/netstat.tproj/iso.c
new file mode 100644 (file)
index 0000000..526e790
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)iso.c      8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * $Header: /cvs/Darwin/Commands/NeXT/network_cmds/netstat.tproj/iso.c,v 1.1.1.2 2000/01/11 01:48:52 wsanchez Exp $
+ * $Source: /cvs/Darwin/Commands/NeXT/network_cmds/netstat.tproj/iso.c,v $
+ */
+/*******************************************************************************
+                 Copyright IBM Corporation 1987
+
+                      All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of IBM not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*******************************************************************************/
+
+/*
+ * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
+ */
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/queue.h>
+#include <errno.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netiso/iso.h>
+#include <netiso/iso_errno.h>
+#include <netiso/clnp.h>
+#include <netiso/esis.h>
+#include <netiso/clnp_stat.h>
+#include <netiso/argo_debug.h>
+#undef satosiso
+#include <netiso/tp_param.h>
+#include <netiso/tp_states.h>
+#include <netiso/tp_pcb.h>
+#include <netiso/tp_stat.h>
+#include <netiso/iso_pcb.h>
+#include <netiso/cltp_var.h>
+#include <netiso/cons.h>
+#ifdef IncStat
+#undef IncStat
+#endif
+#include <netiso/cons_pcb.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "netstat.h"
+
+static void tprintstat __P((struct tp_stat *, int));
+static void isonetprint __P((struct sockaddr_iso *, int));
+static void hexprint __P((int, char *, char *));
+extern void inetprint __P((struct in_addr *, int, char *));
+
+/*
+ *     Dump esis stats
+ */
+void
+esis_stats(off, name)
+       u_long  off;
+       char    *name;
+{
+       struct esis_stat esis_stat;
+
+       if (off == 0 ||
+           kread(off, (char *)&esis_stat, sizeof (struct esis_stat)))
+               return;
+       printf("%s:\n", name);
+       printf("\t%d esh sent, %d esh received\n", esis_stat.es_eshsent,
+               esis_stat.es_eshrcvd);
+       printf("\t%d ish sent, %d ish received\n", esis_stat.es_ishsent,
+               esis_stat.es_ishrcvd);
+       printf("\t%d rd sent, %d rd received\n", esis_stat.es_rdsent,
+               esis_stat.es_rdrcvd);
+       printf("\t%d pdus not sent due to insufficient memory\n",
+               esis_stat.es_nomem);
+       printf("\t%d pdus received with bad checksum\n", esis_stat.es_badcsum);
+       printf("\t%d pdus received with bad version number\n",
+               esis_stat.es_badvers);
+       printf("\t%d pdus received with bad type field\n", esis_stat.es_badtype);
+       printf("\t%d short pdus received\n", esis_stat.es_toosmall);
+}
+
+/*
+ * Dump clnp statistics structure.
+ */
+void
+clnp_stats(off, name)
+       u_long off;
+       char *name;
+{
+       struct clnp_stat clnp_stat;
+
+       if (off == 0 ||
+           kread(off, (char *)&clnp_stat, sizeof (clnp_stat)))
+               return;
+
+       printf("%s:\n\t%d total packets sent\n", name, clnp_stat.cns_sent);
+       printf("\t%d total fragments sent\n", clnp_stat.cns_fragments);
+       printf("\t%d total packets received\n", clnp_stat.cns_total);
+       printf("\t%d with fixed part of header too small\n",
+               clnp_stat.cns_toosmall);
+       printf("\t%d with header length not reasonable\n", clnp_stat.cns_badhlen);
+       printf("\t%d incorrect checksum%s\n",
+               clnp_stat.cns_badcsum, plural(clnp_stat.cns_badcsum));
+       printf("\t%d with unreasonable address lengths\n", clnp_stat.cns_badaddr);
+       printf("\t%d with forgotten segmentation information\n",
+               clnp_stat.cns_noseg);
+       printf("\t%d with an incorrect protocol identifier\n", clnp_stat.cns_noproto);
+       printf("\t%d with an incorrect version\n", clnp_stat.cns_badvers);
+       printf("\t%d dropped because the ttl has expired\n",
+               clnp_stat.cns_ttlexpired);
+       printf("\t%d clnp cache misses\n", clnp_stat.cns_cachemiss);
+       printf("\t%d clnp congestion experience bits set\n",
+               clnp_stat.cns_congest_set);
+       printf("\t%d clnp congestion experience bits received\n",
+               clnp_stat.cns_congest_rcvd);
+}
+/*
+ * Dump CLTP statistics structure.
+ */
+void
+cltp_stats(off, name)
+       u_long off;
+       char *name;
+{
+       struct cltpstat cltpstat;
+
+       if (off == 0 ||
+           kread(off, (char *)&cltpstat, sizeof (cltpstat)))
+               return;
+       printf("%s:\n\t%u incomplete header%s\n", name,
+               cltpstat.cltps_hdrops, plural(cltpstat.cltps_hdrops));
+       printf("\t%u bad data length field%s\n",
+               cltpstat.cltps_badlen, plural(cltpstat.cltps_badlen));
+       printf("\t%u bad checksum%s\n",
+               cltpstat.cltps_badsum, plural(cltpstat.cltps_badsum));
+}
+
+struct tp_pcb tpcb;
+struct isopcb isopcb;
+static struct  socket sockb;
+union  {
+       struct sockaddr_iso     siso;
+       char    data[128];
+} laddr, faddr;
+#define kget(o, p) \
+       (kread((u_long)(o), (char *)&p, sizeof (p)))
+
+static int first = 1;
+
+/*
+ * Print a summary of connections related to an Internet
+ * protocol.  For TP, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+void
+iso_protopr(off, name)
+       u_long off;
+       char *name;
+{
+       struct isopcb cb;
+       register struct isopcb *prev, *next;
+
+       if (off == 0) {
+               printf("%s control block: symbol not in namelist\n", name);
+               return;
+       }
+       if (strcmp(name, "tp") == 0) {
+               tp_protopr(off, name);
+               return;
+       }
+       if (kread(off, (char *)&cb, sizeof(cb)))
+               return;
+       isopcb = cb;
+       prev = (struct isopcb *)off;
+       if (isopcb.isop_next == (struct isopcb *)off)
+               return;
+       while (isopcb.isop_next != (struct isopcb *)off) {
+               next = isopcb.isop_next;
+               kget(next, isopcb);
+               if (isopcb.isop_prev != prev) {
+                       printf("prev 0x%x next 0x%x isop_prev 0x%x isop_next 0x%x???\n",
+                               prev, next, isopcb.isop_prev, isopcb.isop_next);
+                       break;
+               }
+               kget(isopcb.isop_socket, sockb);
+               iso_protopr1((u_long)next, 0);
+               putchar('\n');
+               prev = next;
+       }
+}
+
+void
+iso_protopr1(kern_addr, istp)
+       u_long kern_addr;
+       int istp;
+{
+       if (first) {
+               printf("Active ISO net connections");
+               if (aflag)
+                       printf(" (including servers)");
+               putchar('\n');
+               if (Aflag)
+                       printf("%-8.8s ", "PCB");
+               printf(Aflag ?
+                       "%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
+                       "%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
+                       "Proto", "Recv-Q", "Send-Q",
+                       "Local Address", "Foreign Address", "(state)");
+               first = 0;
+       }
+       if (Aflag)
+                       printf("%8x ",
+                                       (sockb.so_pcb ? (void *)sockb.so_pcb : (void *)kern_addr));
+       printf("%-5.5s %6d %6d ", "tp", sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
+       if (istp && tpcb.tp_lsuffixlen) {
+                       hexprint(tpcb.tp_lsuffixlen, tpcb.tp_lsuffix, "()");
+                       printf("\t");
+       } else if (isopcb.isop_laddr == 0)
+                       printf("*.*\t");
+       else {
+                       if ((char *)isopcb.isop_laddr == ((char *)kern_addr) +
+                                       _offsetof(struct isopcb, isop_sladdr))
+                                       laddr.siso = isopcb.isop_sladdr;
+                       else
+                                       kget(isopcb.isop_laddr, laddr);
+                       isonetprint((struct sockaddr_iso *)&laddr, 1);
+       }
+       if (istp && tpcb.tp_fsuffixlen) {
+                       hexprint(tpcb.tp_fsuffixlen, tpcb.tp_fsuffix, "()");
+                       printf("\t");
+       } else if (isopcb.isop_faddr == 0)
+               printf("*.*\t");
+       else {
+               if ((char *)isopcb.isop_faddr == ((char *)kern_addr) +
+                       _offsetof(struct isopcb, isop_sfaddr))
+                       faddr.siso = isopcb.isop_sfaddr;
+               else
+                       kget(isopcb.isop_faddr, faddr);
+               isonetprint((struct sockaddr_iso *)&faddr, 0);
+       }
+}
+
+void
+tp_protopr(off, name)
+       u_long off;
+       char *name;
+{
+       extern char *tp_sstring[];
+       struct tp_ref *tpr, *tpr_base;
+       struct tp_refinfo tpkerninfo;
+       int size;
+
+       kget(off, tpkerninfo);
+       size = tpkerninfo.tpr_size * sizeof (*tpr);
+       tpr_base = (struct tp_ref *)malloc(size);
+       if (tpr_base == 0)
+               return;
+       kread((u_long)(tpkerninfo.tpr_base), (char *)tpr_base, size);
+       for (tpr = tpr_base; tpr < tpr_base + tpkerninfo.tpr_size; tpr++) {
+               if (tpr->tpr_pcb == 0)
+                       continue;
+               kget(tpr->tpr_pcb, tpcb);
+               if (tpcb.tp_state == ST_ERROR)
+                       printf("undefined tpcb state: 0x%x\n", tpr->tpr_pcb);
+               if (!aflag &&
+                       (tpcb.tp_state == TP_LISTENING ||
+                        tpcb.tp_state == TP_CLOSED ||
+                        tpcb.tp_state == TP_REFWAIT)) {
+                       continue;
+               }
+               kget(tpcb.tp_sock, sockb);
+               if (tpcb.tp_npcb) switch(tpcb.tp_netservice) {
+                       case IN_CLNS:
+                               tp_inproto((u_long)tpkerninfo.tpr_base);
+                               break;
+                       default:
+                               kget(tpcb.tp_npcb, isopcb);
+                               iso_protopr1((u_long)tpcb.tp_npcb, 1);
+                               break;
+               }
+               if (tpcb.tp_state >= tp_NSTATES)
+                       printf(" %d", tpcb.tp_state);
+               else
+                       printf(" %-12.12s", tp_sstring[tpcb.tp_state]);
+               putchar('\n');
+       }
+}
+
+void
+tp_inproto(pcb)
+       u_long pcb;
+{
+       struct inpcb inpcb;
+       kget(tpcb.tp_npcb, inpcb);
+       if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
+               return;
+       if (Aflag)
+               printf("%8x ", pcb);
+       printf("%-5.5s %6d %6d ", "tpip",
+           sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
+       inetprint(&inpcb.inp_laddr, inpcb.inp_lport, "tp");
+       inetprint(&inpcb.inp_faddr, inpcb.inp_fport, "tp");
+}
+
+/*
+ * Pretty print an iso address (net address + port).
+ * If the nflag was specified, use numbers instead of names.
+ */
+
+#ifdef notdef
+char *
+isonetname(iso)
+       register struct iso_addr *iso;
+{
+       struct sockaddr_iso sa;
+       struct iso_hostent *ihe = 0;
+       struct iso_hostent *iso_gethostentrybyaddr();
+       struct iso_hostent *iso_getserventrybytsel();
+       struct iso_hostent Ihe;
+       static char line[80];
+
+       bzero(line, sizeof(line));
+       if( iso->isoa_afi ) {
+               sa.siso_family = AF_ISO;
+               sa.siso_addr = *iso;
+               sa.siso_tsuffix = 0;
+
+               if (!nflag )
+                       ihe = iso_gethostentrybyaddr( &sa, 0, 0 );
+               if( ihe ) {
+                       Ihe = *ihe;
+                       ihe = &Ihe;
+                       sprintf(line, "%s", ihe->isoh_hname);
+               } else {
+                       sprintf(line, "%s", iso_ntoa(iso));
+               }
+       } else {
+               sprintf(line, "*");
+       }
+       return line;
+}
+
+static void
+isonetprint(iso, sufx, sufxlen, islocal)
+       register struct iso_addr *iso;
+       char *sufx;
+       u_short sufxlen;
+       int islocal;
+{
+       struct iso_hostent *iso_getserventrybytsel(), *ihe;
+       struct iso_hostent Ihe;
+       char *line, *cp;
+       int Alen = Aflag?18:22;
+
+       line =  isonetname(iso);
+       cp = index(line, '\0');
+       ihe = (struct iso_hostent *)0;
+
+       if( islocal )
+               islocal = 20;
+       else
+               islocal = 22 + Alen;
+
+       if(Aflag)
+               islocal += 10 ;
+
+       if(!nflag) {
+               if( (cp -line)>10 ) {
+                       cp = line+10;
+                       bzero(cp, sizeof(line)-10);
+               }
+       }
+
+       *cp++ = '.';
+       if(sufxlen) {
+               if( !Aflag && !nflag && (ihe=iso_getserventrybytsel(sufx, sufxlen))) {
+                       Ihe = *ihe;
+                       ihe = &Ihe;
+               }
+               if( ihe && (strlen(ihe->isoh_aname)>0) ) {
+                       sprintf(cp, "%s", ihe->isoh_aname);
+               } else  {
+                       iso_sprinttsel(cp, sufx, sufxlen);
+               }
+       } else
+               sprintf(cp, "*");
+       /*
+       fprintf(stdout, Aflag?" %-18.18s":" %-22.22s", line);
+       */
+
+       if( strlen(line) > Alen ) {
+               fprintf(stdout, " %s", line);
+               fprintf(stdout, "\n %*.s", islocal+Alen," ");
+       } else {
+               fprintf(stdout, " %-*.*s", Alen, Alen,line);
+       }
+}
+#endif
+
+#ifdef notdef
+static void
+x25_protopr(off, name)
+       u_long off;
+       char *name;
+{
+       static char *xpcb_states[] = {
+               "CLOSED",
+               "LISTENING",
+               "CLOSING",
+               "CONNECTING",
+               "ACKWAIT",
+               "OPEN",
+       };
+       register struct isopcb *prev, *next;
+       struct x25_pcb xpcb;
+
+       if (off == 0) {
+               printf("%s control block: symbol not in namelist\n", name);
+               return;
+       }
+       kread(off, &xpcb, sizeof (struct x25_pcb));
+       prev = (struct isopcb *)off;
+       if (xpcb.x_next == (struct isopcb *)off)
+               return;
+       while (xpcb.x_next != (struct isopcb *)off) {
+               next = isopcb.isop_next;
+               kread((u_long)next, &xpcb, sizeof (struct x25_pcb));
+               if (xpcb.x_prev != prev) {
+                       printf("???\n");
+                       break;
+               }
+               kread((u_long)xpcb.x_socket, &sockb, sizeof (sockb));
+
+               if (!aflag &&
+                       xpcb.x_state == LISTENING ||
+                       xpcb.x_state == TP_CLOSED ) {
+                       prev = next;
+                       continue;
+               }
+               if (first) {
+                       printf("Active X25 net connections");
+                       if (aflag)
+                               printf(" (including servers)");
+                       putchar('\n');
+                       if (Aflag)
+                               printf("%-8.8s ", "PCB");
+                       printf(Aflag ?
+                               "%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
+                               "%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
+                               "Proto", "Recv-Q", "Send-Q",
+                               "Local Address", "Foreign Address", "(state)");
+                       first = 0;
+               }
+               printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
+                       sockb.so_snd.sb_cc);
+               isonetprint(&xpcb.x_laddr.siso_addr, &xpcb.x_lport,
+                       sizeof(xpcb.x_lport), 1);
+               isonetprint(&xpcb.x_faddr.siso_addr, &xpcb.x_fport,
+                       sizeof(xpcb.x_lport), 0);
+               if (xpcb.x_state < 0 || xpcb.x_state >= x25_NSTATES)
+                       printf(" 0x0x0x0x0x0x0x0x0x%x", xpcb.x_state);
+               else
+                       printf(" %-12.12s", xpcb_states[xpcb.x_state]);
+               putchar('\n');
+               prev = next;
+       }
+}
+#endif
+
+struct tp_stat tp_stat;
+
+void
+tp_stats(off, name)
+       caddr_t off, name;
+{
+       if (off == 0) {
+               printf("TP not configured\n\n");
+               return;
+       }
+       printf("%s:\n", name);
+       kget(off, tp_stat);
+       tprintstat(&tp_stat, 8);
+}
+
+#define OUT stdout
+
+static void
+tprintstat(s, indent)
+       register struct tp_stat *s;
+       int indent;
+{
+       fprintf(OUT,
+               "%*sReceiving:\n",indent," ");
+       fprintf(OUT,
+               "\t%*s%d variable parameter%s ignored\n", indent," ",
+               s->ts_param_ignored ,plural(s->ts_param_ignored));
+       fprintf(OUT,
+               "\t%*s%d invalid parameter code%s\n", indent, " ",
+               s->ts_inv_pcode ,plural(s->ts_inv_pcode));
+       fprintf(OUT,
+               "\t%*s%d invalid parameter value%s\n", indent, " ",
+               s->ts_inv_pval ,plural(s->ts_inv_pval));
+       fprintf(OUT,
+               "\t%*s%d invalid dutype%s\n", indent, " ",
+               s->ts_inv_dutype ,plural(s->ts_inv_dutype));
+       fprintf(OUT,
+               "\t%*s%d negotiation failure%s\n", indent, " ",
+               s->ts_negotfailed ,plural(s->ts_negotfailed));
+       fprintf(OUT,
+               "\t%*s%d invalid destination reference%s\n", indent, " ",
+               s->ts_inv_dref ,plural(s->ts_inv_dref));
+       fprintf(OUT,
+               "\t%*s%d invalid suffix parameter%s\n", indent, " ",
+               s->ts_inv_sufx ,plural(s->ts_inv_sufx));
+       fprintf(OUT,
+               "\t%*s%d invalid length\n",indent, " ", s->ts_inv_length);
+       fprintf(OUT,
+               "\t%*s%d invalid checksum%s\n", indent, " ",
+               s->ts_bad_csum ,plural(s->ts_bad_csum));
+       fprintf(OUT,
+               "\t%*s%d DT%s out of order\n", indent, " ",
+               s->ts_dt_ooo ,plural(s->ts_dt_ooo));
+       fprintf(OUT,
+               "\t%*s%d DT%s not in window\n", indent, " ",
+               s->ts_dt_niw ,plural(s->ts_dt_niw));
+       fprintf(OUT,
+               "\t%*s%d duplicate DT%s\n", indent, " ",
+               s->ts_dt_dup ,plural(s->ts_dt_dup));
+       fprintf(OUT,
+                       "\t%*s%d XPD%s not in window\n", indent, " ",
+                       s->ts_xpd_niw ,plural(s->ts_xpd_niw));
+               fprintf(OUT,
+                       "\t%*s%d XPD%s w/o credit to stash\n", indent, " ",
+               s->ts_xpd_dup ,plural(s->ts_xpd_dup));
+       fprintf(OUT,
+               "\t%*s%d time%s local credit reneged\n", indent, " ",
+               s->ts_lcdt_reduced ,plural(s->ts_lcdt_reduced));
+       fprintf(OUT,
+               "\t%*s%d concatenated TPDU%s\n", indent, " ",
+               s->ts_concat_rcvd ,plural(s->ts_concat_rcvd));
+       fprintf(OUT,
+               "%*sSending:\n", indent, " ");
+       fprintf(OUT,
+               "\t%*s%d XPD mark%s discarded\n", indent, " ",
+               s->ts_xpdmark_del ,plural(s->ts_xpdmark_del));
+       fprintf(OUT,
+               "\t%*sXPD stopped data flow %d time%s\n", indent, " ",
+               s->ts_xpd_intheway ,plural(s->ts_xpd_intheway));
+       fprintf(OUT,
+               "\t%*s%d time%s foreign window closed\n", indent, " ",
+               s->ts_zfcdt ,plural(s->ts_zfcdt));
+       fprintf(OUT,
+               "%*sMiscellaneous:\n", indent, " ");
+       fprintf(OUT,
+               "\t%*s%d small mbuf%s\n", indent, " ",
+               s->ts_mb_small ,plural(s->ts_mb_small));
+       fprintf(OUT,
+               "\t%*s%d cluster%s\n", indent, " ",
+               s->ts_mb_cluster, plural(s->ts_mb_cluster));
+       fprintf(OUT,
+               "\t%*s%d source quench \n",indent, " ",
+               s->ts_quench);
+       fprintf(OUT,
+               "\t%*s%d dec bit%s\n", indent, " ",
+               s->ts_rcvdecbit, plural(s->ts_rcvdecbit));
+       fprintf(OUT,
+               "\t%*sM:L ( M mbuf chains of length L)\n", indent, " ");
+       {
+               register int j;
+
+               fprintf(OUT, "\t%*s%d: over 16\n", indent, " ",
+               s->ts_mb_len_distr[0]);
+               for( j=1; j<=8; j++) {
+                       fprintf(OUT,
+                               "\t%*s%d: %d\t\t%d: %d\n", indent, " ",
+                               s->ts_mb_len_distr[j],j,
+                               s->ts_mb_len_distr[j<<1],j<<1
+                               );
+               }
+       }
+       fprintf(OUT,
+               "\t%*s%d EOT rcvd\n",  indent, " ", s->ts_eot_input);
+       fprintf(OUT,
+               "\t%*s%d EOT sent\n",  indent, " ", s->ts_EOT_sent);
+       fprintf(OUT,
+               "\t%*s%d EOT indication%s\n",  indent, " ",
+               s->ts_eot_user ,plural(s->ts_eot_user));
+
+       fprintf(OUT,
+               "%*sConnections:\n", indent, " ");
+       fprintf(OUT,
+               "\t%*s%d connection%s used extended format\n",  indent, " ",
+               s->ts_xtd_fmt ,plural(s->ts_xtd_fmt));
+       fprintf(OUT,
+               "\t%*s%d connection%s allowed transport expedited data\n",  indent, " ",
+               s->ts_use_txpd ,plural(s->ts_use_txpd));
+       fprintf(OUT,
+               "\t%*s%d connection%s turned off checksumming\n",  indent, " ",
+               s->ts_csum_off ,plural(s->ts_csum_off));
+       fprintf(OUT,
+               "\t%*s%d connection%s dropped due to retrans limit\n",  indent, " ",
+               s->ts_conn_gaveup ,plural(s->ts_conn_gaveup));
+       fprintf(OUT,
+               "\t%*s%d tp 4 connection%s\n",  indent, " ",
+               s->ts_tp4_conn ,plural(s->ts_tp4_conn));
+       fprintf(OUT,
+               "\t%*s%d tp 0 connection%s\n",  indent, " ",
+               s->ts_tp0_conn ,plural(s->ts_tp0_conn));
+    {
+               register int j;
+               static char *name[]= {
+                       "~LOCAL, PDN",
+                       "~LOCAL,~PDN",
+                       " LOCAL,~PDN",
+                       " LOCAL, PDN"
+               };
+
+               fprintf(OUT,
+                       "\n%*sRound trip times, listed in ticks:\n", indent, " ");
+               fprintf(OUT,
+                       "\t%*s%11.11s  %12.12s | %12.12s | %s\n", indent, " ",
+                               "Category",
+                               "Smoothed avg", "Deviation", "Deviation/Avg");
+               for (j = 0; j <= 3; j++) {
+                       fprintf(OUT,
+                               "\t%*s%11.11s: %-11d | %-11d | %-11d | %-11d\n", indent, " ",
+                               name[j],
+                               s->ts_rtt[j],
+                               s->ts_rtt[j],
+                               s->ts_rtv[j],
+                               s->ts_rtv[j]);
+               }
+       }
+       fprintf(OUT,
+"\n%*sTpdus RECVD [%d valid, %3.6f %% of total (%d); %d dropped]\n",indent," ",
+               s->ts_tpdu_rcvd ,
+               ((s->ts_pkt_rcvd > 0) ?
+                       ((100 * (float)s->ts_tpdu_rcvd)/(float)s->ts_pkt_rcvd)
+                       : 0),
+               s->ts_pkt_rcvd,
+               s->ts_recv_drop );
+
+       fprintf(OUT,
+               "\t%*sDT  %6d   AK  %6d   DR  %4d   CR  %4d \n", indent, " ",
+               s->ts_DT_rcvd, s->ts_AK_rcvd, s->ts_DR_rcvd, s->ts_CR_rcvd);
+       fprintf(OUT,
+               "\t%*sXPD %6d   XAK %6d   DC  %4d   CC  %4d   ER  %4d\n",  indent, " ",
+               s->ts_XPD_rcvd, s->ts_XAK_rcvd, s->ts_DC_rcvd, s->ts_CC_rcvd,
+               s->ts_ER_rcvd);
+       fprintf(OUT,
+               "\n%*sTpdus SENT [%d total, %d dropped]\n",  indent, " ",
+               s->ts_tpdu_sent, s->ts_send_drop);
+
+       fprintf(OUT,
+               "\t%*sDT  %6d   AK  %6d   DR  %4d   CR  %4d \n", indent, " ",
+               s->ts_DT_sent, s->ts_AK_sent, s->ts_DR_sent, s->ts_CR_sent);
+       fprintf(OUT,
+               "\t%*sXPD %6d   XAK %6d   DC  %4d   CC  %4d   ER  %4d\n",  indent, " ",
+               s->ts_XPD_sent, s->ts_XAK_sent, s->ts_DC_sent, s->ts_CC_sent,
+               s->ts_ER_sent);
+
+       fprintf(OUT,
+               "\n%*sRetransmissions:\n", indent, " ");
+#define PERCENT(X,Y) (((Y)>0)?((100 *(float)(X)) / (float) (Y)):0)
+
+       fprintf(OUT,
+       "\t%*sCR  %6d   CC  %6d   DR  %6d \n", indent, " ",
+               s->ts_retrans_cr, s->ts_retrans_cc, s->ts_retrans_dr);
+       fprintf(OUT,
+       "\t%*sDT  %6d (%5.2f%%)\n", indent, " ",
+               s->ts_retrans_dt,
+               PERCENT(s->ts_retrans_dt, s->ts_DT_sent));
+       fprintf(OUT,
+       "\t%*sXPD %6d (%5.2f%%)\n",  indent, " ",
+               s->ts_retrans_xpd,
+               PERCENT(s->ts_retrans_xpd, s->ts_XPD_sent));
+
+
+       fprintf(OUT,
+               "\n%*sE Timers: [%6d ticks]\n", indent, " ", s->ts_Eticks);
+       fprintf(OUT,
+               "%*s%6d timer%s set \t%6d timer%s expired \t%6d timer%s cancelled\n",indent, " ",
+               s->ts_Eset ,plural(s->ts_Eset),
+               s->ts_Eexpired ,plural(s->ts_Eexpired),
+               s->ts_Ecan_act ,plural(s->ts_Ecan_act));
+
+       fprintf(OUT,
+               "\n%*sC Timers: [%6d ticks]\n",  indent, " ",s->ts_Cticks);
+       fprintf(OUT,
+       "%*s%6d timer%s set \t%6d timer%s expired \t%6d timer%s cancelled\n",
+               indent, " ",
+               s->ts_Cset ,plural(s->ts_Cset),
+               s->ts_Cexpired ,plural(s->ts_Cexpired),
+               s->ts_Ccan_act ,plural(s->ts_Ccan_act));
+       fprintf(OUT,
+               "%*s%6d inactive timer%s cancelled\n", indent, " ",
+               s->ts_Ccan_inact ,plural(s->ts_Ccan_inact));
+
+       fprintf(OUT,
+               "\n%*sPathological debugging activity:\n", indent, " ");
+       fprintf(OUT,
+               "\t%*s%6d CC%s sent to zero dref\n", indent, " ",
+               s->ts_zdebug ,plural(s->ts_zdebug));
+       /* SAME LINE AS ABOVE */
+       fprintf(OUT,
+               "\t%*s%6d random DT%s dropped\n", indent, " ",
+               s->ts_ydebug ,plural(s->ts_ydebug));
+       fprintf(OUT,
+               "\t%*s%6d illegally large XPD TPDU%s\n", indent, " ",
+               s->ts_vdebug ,plural(s->ts_vdebug));
+       fprintf(OUT,
+               "\t%*s%6d faked reneging of cdt\n", indent, " ",
+               s->ts_ldebug );
+
+       fprintf(OUT,
+               "\n%*sACK reasons:\n", indent, " ");
+       fprintf(OUT, "\t%*s%6d not acked immediately\n", indent, " ",
+               s->ts_ackreason[_ACK_DONT_] );
+       fprintf(OUT, "\t%*s%6d strategy==each\n", indent, " ",
+               s->ts_ackreason[_ACK_STRAT_EACH_] );
+       fprintf(OUT, "\t%*s%6d strategy==fullwindow\n", indent, " ",
+               s->ts_ackreason[_ACK_STRAT_FULLWIN_] );
+       fprintf(OUT, "\t%*s%6d duplicate DT\n", indent, " ",
+               s->ts_ackreason[_ACK_DUP_] );
+       fprintf(OUT, "\t%*s%6d EOTSDU\n", indent, " ",
+               s->ts_ackreason[_ACK_EOT_] );
+       fprintf(OUT, "\t%*s%6d reordered DT\n", indent, " ",
+               s->ts_ackreason[_ACK_REORDER_] );
+       fprintf(OUT, "\t%*s%6d user rcvd\n", indent, " ",
+               s->ts_ackreason[_ACK_USRRCV_] );
+       fprintf(OUT, "\t%*s%6d fcc reqd\n", indent, " ",
+               s->ts_ackreason[_ACK_FCC_] );
+}
+#ifndef SSEL
+#define SSEL(s) ((s)->siso_tlen + TSEL(s))
+#define PSEL(s) ((s)->siso_slen + SSEL(s))
+#endif
+
+static void
+isonetprint(siso, islocal)
+       register struct sockaddr_iso *siso;
+       int islocal;
+{
+       hexprint(siso->siso_nlen, siso->siso_addr.isoa_genaddr, "{}");
+       if (siso->siso_tlen || siso->siso_slen || siso->siso_plen)
+               hexprint(siso->siso_tlen, TSEL(siso), "()");
+       if (siso->siso_slen || siso->siso_plen)
+               hexprint(siso->siso_slen, SSEL(siso), "[]");
+       if (siso->siso_plen)
+               hexprint(siso->siso_plen, PSEL(siso), "<>");
+       putchar(' ');
+}
+
+static char hexlist[] = "0123456789abcdef", obuf[128];
+
+static void
+hexprint(n, buf, delim)
+       int n;
+       char *buf, *delim;
+{
+       register u_char *in = (u_char *)buf, *top = in + n;
+       register char *out = obuf;
+       register int i;
+
+       if (n == 0)
+               return;
+       while (in < top) {
+               i = *in++;
+               *out++ = '.';
+               if (i > 0xf) {
+                       out[1] = hexlist[i & 0xf];
+                       i >>= 4;
+                       out[0] = hexlist[i];
+                       out += 2;
+               } else
+                       *out++ = hexlist[i];
+       }
+       *obuf = *delim; *out++ = delim[1]; *out = 0;
+       printf("%s", obuf);
+}
diff --git a/netstat.tproj/main.c b/netstat.tproj/main.c
new file mode 100644 (file)
index 0000000..8ca3a72
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char const copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993\n\
+       Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)main.c     8.4 (Berkeley) 3/1/94";
+#endif
+static const char rcsid[] =
+       "$Id: main.c,v 1.2 2000/06/16 03:37:29 lindak Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $Id: main.c,v 1.2 2000/06/16 03:37:29 lindak Exp $
+ *
+ */
+
+
+static struct nlist nl[] = {
+#define        N_IFNET         0
+       { "_ifnet" },
+#define        N_IMP           1
+       { "_imp_softc" },
+#define        N_RTSTAT        2
+       { "_rtstat" },
+#define        N_UNIXSW        3
+       { "_localsw" },
+#define N_IDP          4
+       { "_nspcb"},
+#define N_IDPSTAT      5
+       { "_idpstat"},
+#define N_SPPSTAT      6
+       { "_spp_istat"},
+#define N_NSERR                7
+       { "_ns_errstat"},
+#define        N_CLNPSTAT      8
+       { "_clnp_stat"},
+#define        IN_NOTUSED      9
+       { "_tp_inpcb" },
+#define        ISO_TP          10
+       { "_tp_refinfo" },
+#define        N_TPSTAT        11
+       { "_tp_stat" },
+#define        N_ESISSTAT      12
+       { "_esis_stat"},
+#define N_NIMP         13
+       { "_nimp"},
+#define N_RTREE                14
+       { "_rt_tables"},
+#define N_CLTP         15
+       { "_cltb"},
+#define N_CLTPSTAT     16
+       { "_cltpstat"},
+#define        N_NFILE         17
+       { "_nfile" },
+#define        N_FILE          18
+       { "_file" },
+#define N_MRTSTAT      19
+       { "_mrtstat" },
+#define N_MFCTABLE     20
+       { "_mfctable" },
+#define N_VIFTABLE     21
+       { "_viftable" },
+#define N_IPX          22
+       { "_ipxpcb"},
+#define N_IPXSTAT      23
+       { "_ipxstat"},
+#define N_SPXSTAT      24
+       { "_spx_istat"},
+#define N_DDPSTAT      25
+       { "_ddpstat"},
+#define N_DDPCB                26
+       { "_ddpcb"},
+#define N_MBSTAT       27
+       {"_mbstat"},
+       { "" },
+};
+
+
+
+struct protox {
+       u_char  pr_index;               /* index into nlist of cb head */
+       u_char  pr_sindex;              /* index into nlist of stat block */
+       u_char  pr_wanted;              /* 1 if wanted, 0 otherwise */
+       void    (*pr_cblocks)();        /* control blocks printing routine */
+       void    (*pr_stats)();          /* statistics printing routine */
+       char    *pr_name;               /* well-known name */
+       int     pr_usesysctl;           /* true if we use sysctl, not kvm */
+} protox[] = {
+       { -1,           -1,             1,      protopr,
+         tcp_stats,    "tcp",          IPPROTO_TCP },
+       { -1,           -1,             1,      protopr,
+         udp_stats,    "udp",          IPPROTO_UDP },
+       { -1,           -1,             1,      protopr,
+         NULL,         "divert",       IPPROTO_DIVERT },
+       { -1,           -1,             1,      protopr,
+         ip_stats,     "ip",           IPPROTO_RAW },
+       { -1,           -1,             1,      protopr,
+         icmp_stats,   "icmp",         IPPROTO_ICMP },
+       { -1,           -1,             1,      protopr,
+         igmp_stats,   "igmp",         IPPROTO_IGMP },
+       { -1,           -1,             0,      0,
+         0,            0 }
+};
+
+#ifdef UNIX_ATALK
+struct protox atalkprotox[] = {
+       { N_DDPCB,      N_DDPSTAT,      1,      atalkprotopr,
+         ddp_stats,    "ddp" },
+       { -1,           -1,             0,      0,
+         0,            0 }
+};
+#endif
+
+#ifdef IPX
+struct protox ipxprotox[] = {
+       { N_IPX,        N_IPXSTAT,      1,      ipxprotopr,
+         ipx_stats,    "ipx",          0 },
+       { N_IPX,        N_SPXSTAT,      1,      ipxprotopr,
+         spx_stats,    "spx",          0 },
+       { -1,           -1,             0,      0,
+         0,            0,              0 }
+};
+#endif
+
+#ifdef NS
+struct protox nsprotox[] = {
+       { N_IDP,        N_IDPSTAT,      1,      nsprotopr,
+         idp_stats,    "idp" },
+       { N_IDP,        N_SPPSTAT,      1,      nsprotopr,
+         spp_stats,    "spp" },
+       { -1,           N_NSERR,        1,      0,
+         nserr_stats,  "ns_err" },
+       { -1,           -1,             0,      0,
+         0,            0 }
+};
+#endif
+
+#ifdef ISO
+struct protox isoprotox[] = {
+       { ISO_TP,       N_TPSTAT,       1,      iso_protopr,
+         tp_stats,     "tp" },
+       { N_CLTP,       N_CLTPSTAT,     1,      iso_protopr,
+         cltp_stats,   "cltp" },
+       { -1,           N_CLNPSTAT,     1,       0,
+         clnp_stats,   "clnp"},
+       { -1,           N_ESISSTAT,     1,       0,
+         esis_stats,   "esis"},
+       { -1,           -1,             0,      0,
+         0,            0 }
+};
+#endif
+
+struct protox *protoprotox[] = { protox, 
+
+#ifdef IPX
+ipxprotox, 
+#endif
+
+#ifdef UNIX_ATALK
+atalkprotox,
+#endif
+
+#ifdef NS
+                                        nsprotox, 
+#endif
+#ifdef ISO
+                                        isoprotox, 
+#endif
+                                        NULL };
+
+static void printproto __P((struct protox *, char *));
+static void usage __P((void));
+static struct protox *name2protox __P((char *));
+static struct protox *knownname __P((char *));
+
+static kvm_t *kvmd;
+char *nlistf = NULL, *memf = NULL;
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct protoent *p;
+       register struct protox *tp;     /* for printing cblocks & stats */
+       int ch;
+
+       af = AF_UNSPEC;
+
+       while ((ch = getopt(argc, argv, "Aabdf:ghI:iM:mN:np:rstuw:")) != -1)
+               switch(ch) {
+               case 'A':
+                       Aflag = 1;
+                       break;
+               case 'a':
+                       aflag = 1;
+                       break;
+               case 'b':
+                       bflag = 1;
+                       break;
+               case 'd':
+                       dflag = 1;
+                       break;
+               case 'f':
+#ifdef NS
+                       if (strcmp(optarg, "ns") == 0)
+                               af = AF_NS;
+                       else
+#endif
+                       if (strcmp(optarg, "ipx") == 0)
+                               af = AF_IPX;
+                       else if (strcmp(optarg, "inet") == 0)
+                               af = AF_INET;
+                       else if (strcmp(optarg, "unix") == 0)
+                               af = AF_UNIX;
+                       else if (strcmp(optarg, "local") == 0)
+                               af = AF_LOCAL;
+                       else if (strcmp(optarg, "atalk") == 0)
+                               af = AF_APPLETALK;
+#ifdef ISO
+                       else if (strcmp(optarg, "iso") == 0)
+                               af = AF_ISO;
+#endif
+                       else {
+                               errx(1, "%s: unknown address family", optarg);
+                       }
+                       break;
+               case 'g':
+                       gflag = 1;
+                       break;
+               case 'I': {
+                       char *cp;
+
+                       iflag = 1;
+                       for (cp = interface = optarg; isalpha(*cp); cp++)
+                               continue;
+                       unit = atoi(cp);
+                       break;
+               }
+               case 'i':
+                       iflag = 1;
+                       break;
+               case 'M':
+                       memf = optarg;
+                       break;
+               case 'm':
+                       mflag = 1;
+                       break;
+               case 'N':
+                       nlistf = optarg;
+                       break;
+               case 'n':
+                       nflag = 1;
+                       break;
+               case 'p':
+                       if ((tp = name2protox(optarg)) == NULL) {
+                               errx(1, 
+                                    "%s: unknown or uninstrumented protocol",
+                                    optarg);
+                       }
+                       pflag = 1;
+                       break;
+               case 'r':
+                       rflag = 1;
+                       break;
+               case 's':
+                       ++sflag;
+                       break;
+               case 't':
+                       tflag = 1;
+                       break;
+               case 'u':
+                       af = AF_UNIX;
+                       break;
+               case 'w':
+                       interval = atoi(optarg);
+                       iflag = 1;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argv += optind;
+       argc -= optind;
+
+#define        BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+       if (*argv) {
+               if (isdigit(**argv)) {
+                       interval = atoi(*argv);
+                       if (interval <= 0)
+                               usage();
+                       ++argv;
+                       iflag = 1;
+               }
+               if (*argv) {
+                       nlistf = *argv;
+                       if (*++argv)
+                               memf = *argv;
+               }
+       }
+#endif
+
+       /*
+        * Discard setgid privileges if not the running kernel so that bad
+        * guys can't print interesting stuff from kernel memory.
+        */
+       if (nlistf != NULL || memf != NULL)
+               setgid(getgid());
+
+       if (mflag) {
+               kread(0,0,0);
+               mbpr(nl[N_MBSTAT].n_value);
+               exit(0);
+       }
+       if (pflag) {
+               if (!tp->pr_stats) {
+                       printf("%s: no stats routine\n", tp->pr_name);
+                       exit(0);
+               }
+               if (tp->pr_usesysctl) {
+                       (*tp->pr_stats)(tp->pr_usesysctl, tp->pr_name);
+               } else {
+                       kread(0, 0, 0);
+                       (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
+                                       tp->pr_name);
+               }
+               exit(0);
+       }
+#if 0
+       /*
+        * Keep file descriptors open to avoid overhead
+        * of open/close on each call to get* routines.
+        */
+       sethostent(1);
+       setnetent(1);
+#else
+       /*
+        * This does not make sense any more with DNS being default over
+        * the files.  Doing a setXXXXent(1) causes a tcp connection to be
+        * used for the queries, which is slower.
+        */
+#endif
+       if (iflag) {
+               kread(0, 0, 0);
+               intpr(interval, nl[N_IFNET].n_value);
+               exit(0);
+       }
+       if (rflag) {
+               kread(0, 0, 0);
+               if (sflag)
+                       rt_stats(nl[N_RTSTAT].n_value);
+               else
+                       routepr(nl[N_RTREE].n_value);
+               exit(0);
+       }
+       if (gflag) {
+               kread(0, 0, 0);
+               if (sflag)
+                       mrt_stats(nl[N_MRTSTAT].n_value);
+               else
+                       mroutepr(nl[N_MFCTABLE].n_value,
+                           nl[N_VIFTABLE].n_value);
+               exit(0);
+       }
+       if (af == AF_INET || af == AF_UNSPEC) {
+               setprotoent(1);
+               setservent(1);
+               /* ugh, this is O(MN) ... why do we do this? */
+               while ((p = getprotoent())) {
+                       for (tp = protox; tp->pr_name; tp++)
+                               if (strcmp(tp->pr_name, p->p_name) == 0)
+                                       break;
+                       if (tp->pr_name == 0 || tp->pr_wanted == 0)
+                               continue;
+                       printproto(tp, p->p_name);
+               }
+               endprotoent();
+       }
+
+#ifdef IPX
+       if (af == AF_IPX || af == AF_UNSPEC) {
+               kread(0, 0, 0);
+               for (tp = ipxprotox; tp->pr_name; tp++)
+                       printproto(tp, tp->pr_name);
+       }
+#endif
+#ifdef UNIX_ATALK
+       if (af == AF_APPLETALK || af == AF_UNSPEC)
+               for (tp = atalkprotox; tp->pr_name; tp++)
+                       printproto(tp, tp->pr_name);
+#endif
+#ifdef NS
+       if (af == AF_NS || af == AF_UNSPEC)
+               for (tp = nsprotox; tp->pr_name; tp++)
+                       printproto(tp, tp->pr_name);
+#endif
+#ifdef ISO
+       if (af == AF_ISO || af == AF_UNSPEC)
+               for (tp = isoprotox; tp->pr_name; tp++)
+                       printproto(tp, tp->pr_name);
+#endif
+       if ((af == AF_UNIX || af == AF_LOCAL || af == AF_UNSPEC) && !sflag)
+               unixpr();
+       exit(0);
+}
+
+/*
+ * Print out protocol statistics or control blocks (per sflag).
+ * If the interface was not specifically requested, and the symbol
+ * is not in the namelist, ignore this one.
+ */
+static void
+printproto(tp, name)
+       register struct protox *tp;
+       char *name;
+{
+       void (*pr)();
+       u_long off;
+
+       if (sflag) {
+               pr = tp->pr_stats;
+               off = tp->pr_usesysctl ? tp->pr_usesysctl 
+                       : nl[tp->pr_sindex].n_value;
+       } else {
+               pr = tp->pr_cblocks;
+               off = tp->pr_usesysctl ? tp->pr_usesysctl
+                       : nl[tp->pr_index].n_value;
+       }
+       if (pr != NULL && (off || af != AF_UNSPEC))
+               (*pr)(off, name);
+}
+
+/*
+ * Read kernel memory, return 0 on success.
+ */
+int
+kread(addr, buf, size)
+       u_long addr;
+       char *buf;
+       int size;
+{
+       if (kvmd == 0) {
+               /*
+                * XXX.
+                */
+               kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
+               if (kvmd != NULL) {
+                       if (kvm_nlist(kvmd, nl) < 0) {
+                               if(nlistf)
+                                       errx(1, "%s: kvm_nlist: %s", nlistf,
+                                            kvm_geterr(kvmd));
+                               else
+                                       errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
+                       }
+
+                       if (nl[0].n_type == 0) {
+                               if(nlistf)
+                                       errx(1, "%s: no namelist", nlistf);
+                               else
+                                       errx(1, "no namelist");
+                       }
+               } else {
+                       warnx("kvm not available");
+                       return(-1);
+               }
+       }
+       if (!buf)
+               return (0);
+       if (kvm_read(kvmd, addr, buf, size) != size) {
+               warnx("%s", kvm_geterr(kvmd));
+               return (-1);
+       }
+       return (0);
+}
+
+char *
+plural(n)
+       int n;
+{
+       return (n != 1 ? "s" : "");
+}
+
+char *
+plurales(n)
+       int n;
+{
+       return (n != 1 ? "es" : "");
+}
+
+/*
+ * Find the protox for the given "well-known" name.
+ */
+static struct protox *
+knownname(name)
+       char *name;
+{
+       struct protox **tpp, *tp;
+
+       for (tpp = protoprotox; *tpp; tpp++)
+               for (tp = *tpp; tp->pr_name; tp++)
+                       if (strcmp(tp->pr_name, name) == 0)
+                               return (tp);
+       return (NULL);
+}
+
+/*
+ * Find the protox corresponding to name.
+ */
+static struct protox *
+name2protox(name)
+       char *name;
+{
+       struct protox *tp;
+       char **alias;                   /* alias from p->aliases */
+       struct protoent *p;
+
+       /*
+        * Try to find the name in the list of "well-known" names. If that
+        * fails, check if name is an alias for an Internet protocol.
+        */
+       if ((tp = knownname(name)))
+               return (tp);
+
+       setprotoent(1);                 /* make protocol lookup cheaper */
+       while ((p = getprotoent())) {
+               /* assert: name not same as p->name */
+               for (alias = p->p_aliases; *alias; alias++)
+                       if (strcmp(name, *alias) == 0) {
+                               endprotoent();
+                               return (knownname(p->p_name));
+                       }
+       }
+       endprotoent();
+       return (NULL);
+}
+
+static void
+usage()
+{
+       (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
+"usage: netstat [-Aan] [-f address_family] [-M core] [-N system]",
+"       netstat [-bdghimnrs] [-f address_family] [-M core] [-N system]",
+"       netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]",
+"       netstat [-M core] [-N system] [-p protocol]");
+       exit(1);
+}
+
+void
+trimdomain(cp)
+       char *cp;
+{
+       static char domain[MAXHOSTNAMELEN + 1];
+       static int first = 1;
+       char *s;
+
+       if (first) {
+               first = 0;
+               if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+                   (s = strchr(domain, '.')))
+                       (void) strcpy(domain, s + 1);
+               else
+                       domain[0] = 0;
+       }
+
+       if (domain[0]) {
+               while ((cp = strchr(cp, '.'))) {
+                       if (!strcasecmp(cp + 1, domain)) {
+                               *cp = 0;        /* hit it */
+                               break;
+                       } else {
+                               cp++;
+                       }
+               }
+       }
+}
+
diff --git a/netstat.tproj/mbuf.c b/netstat.tproj/mbuf.c
new file mode 100644 (file)
index 0000000..95f81b4
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/mbuf.h>
+
+#include <stdio.h>
+#include "netstat.h"
+#include <netat/sysglue.h>    /* To get Appletalk message/mbuf types */
+
+#define        YES     1
+typedef int bool;
+
+struct mbstat mbstat;
+
+static struct mbtypes {
+       int     mt_type;
+       char    *mt_name;
+} mbtypes[] = {
+       { MT_DATA,      "data" },
+       { MT_OOBDATA,   "oob data" },
+       { MT_CONTROL,   "ancillary data" },
+       { MT_HEADER,    "packet headers" },
+       { MT_SOCKET,    "socket structures" },                  /* XXX */
+       { MT_PCB,       "protocol control blocks" },            /* XXX */
+       { MT_RTABLE,    "routing table entries" },              /* XXX */
+       { MT_HTABLE,    "IMP host table entries" },             /* XXX */
+       { MT_ATABLE,    "address resolution tables" },
+       { MT_FTABLE,    "fragment reassembly queue headers" },  /* XXX */
+       { MT_SONAME,    "socket names and addresses" },
+       { MT_SOOPTS,    "socket options" },
+       { MT_RIGHTS,    "access rights" },
+       { MT_IFADDR,    "interface addresses" },                /* XXX */
+       { MSG_DATA,     "Appletalk data blocks"},
+       { MSG_PROTO,    "Appletalk internal msgs"},
+       { MSG_IOCTL,    "Appletalk ioctl requests"},
+       { MSG_ERROR,    "Appletalk error indicators"},
+       { MSG_HANGUP,   "Appletalk termination requests"},
+       { MSG_IOCACK,   "Appletalk ioctl acks"},
+       { MSG_IOCNAK,   "Appletalk ioctl failure indicators"},
+       { MSG_CTL,      "Appletalk control msgs"},
+       { 0, 0 }
+};
+
+int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short);
+bool seen[256];                        /* "have we seen this type yet?" */
+
+/*
+ * Print mbuf statistics.
+ */
+void
+mbpr(mbaddr)
+       u_long mbaddr;
+{
+       register int totmem, totfree, totmbufs;
+       register int i;
+       register struct mbtypes *mp;
+
+       if (nmbtypes != 256) {
+               fprintf(stderr,
+                   "netstat: unexpected change to mbstat; check source\n");
+               return;
+       }
+       if (mbaddr == 0) {
+               fprintf(stderr, "netstat: mbstat: symbol not in namelist\n");
+               return;
+       }
+       if (kread(mbaddr, (char *)&mbstat, sizeof (mbstat)))
+               return;
+
+       totmbufs = 0;
+       for (mp = mbtypes; mp->mt_name; mp++)
+               totmbufs += mbstat.m_mtypes[mp->mt_type];
+       printf("%u mbufs in use:\n", totmbufs);
+       for (mp = mbtypes; mp->mt_name; mp++)
+               if (mbstat.m_mtypes[mp->mt_type]) {
+                       seen[mp->mt_type] = YES;
+                       printf("\t%u mbufs allocated to %s\n",
+                           mbstat.m_mtypes[mp->mt_type], mp->mt_name);
+               }
+       seen[MT_FREE] = YES;
+       for (i = 0; i < nmbtypes; i++)
+               if (!seen[i] && mbstat.m_mtypes[i]) {
+                       printf("\t%u mbufs allocated to <mbuf type %d>\n",
+                           mbstat.m_mtypes[i], i);
+               }
+       printf("%u/%u mbuf clusters in use\n",
+              (unsigned int)(mbstat.m_clusters - mbstat.m_clfree),
+              (unsigned int)mbstat.m_clusters);
+       totmem = totmbufs * MSIZE + mbstat.m_clusters * MCLBYTES;
+       totfree = mbstat.m_clfree * MCLBYTES;
+       printf("%u Kbytes allocated to network (%d%% in use)\n",
+               totmem / 1024, (totmem - totfree) * 100 / totmem);
+       printf("%u requests for memory denied\n",
+              (unsigned int)mbstat.m_drops);
+       printf("%u requests for memory delayed\n", (unsigned int)mbstat.m_wait);
+       printf("%u calls to protocol drain routines\n",
+              (unsigned int)mbstat.m_drain);
+}
diff --git a/netstat.tproj/mroute.c b/netstat.tproj/mroute.c
new file mode 100644 (file)
index 0000000..03e47cc
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989 Stephen Deering
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)mroute.c    8.2 (Berkeley) 4/28/95
+ */
+
+/*
+ * Print DVMRP multicast routing structures and statistics.
+ *
+ * MROUTING 1.0
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/igmp.h>
+#include <net/route.h>
+#include <netinet/ip_mroute.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "netstat.h"
+
+void
+mroutepr(mfcaddr, vifaddr)
+       u_long mfcaddr, vifaddr;
+{
+       u_int mrtproto;
+       struct mfc *mfctable[MFCTBLSIZ];
+       struct vif viftable[MAXVIFS];
+       struct mfc mfc, *m;
+       register struct vif *v;
+       register vifi_t vifi;
+       register int i;
+       register int banner_printed;
+       register int saved_nflag;
+       vifi_t maxvif = 0;
+
+       if (mfcaddr == 0 || vifaddr == 0) {
+               printf("No multicast routing compiled into this system.\n");
+               return;
+       }
+
+       saved_nflag = nflag;
+       nflag = 1;
+
+       kread(vifaddr, (char *)&viftable, sizeof(viftable));
+       banner_printed = 0;
+       for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
+               if (v->v_lcl_addr.s_addr == 0)
+                       continue;
+
+               maxvif = vifi;
+               if (!banner_printed) {
+                       printf("\nVirtual Interface Table\n"
+                              " Vif   Thresh   Rate   Local-Address   "
+                              "Remote-Address    Pkts-In   Pkts-Out\n");
+                       banner_printed = 1;
+               }
+
+               printf(" %2u    %6u   %4d   %-15.15s",
+                                       /* opposite math of add_vif() */
+                   vifi, v->v_threshold, v->v_rate_limit * 1000 / 1024, 
+                   routename(v->v_lcl_addr.s_addr));
+               printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ?
+                   routename(v->v_rmt_addr.s_addr) : "");
+
+               printf(" %9lu  %9lu\n", v->v_pkt_in, v->v_pkt_out);
+       }
+       if (!banner_printed)
+               printf("\nVirtual Interface Table is empty\n");
+
+       kread(mfcaddr, (char *)&mfctable, sizeof(mfctable));
+       banner_printed = 0;
+       for (i = 0; i < MFCTBLSIZ; ++i) {
+               m = mfctable[i];
+               while(m) {
+                       kread((u_long)m, (char *)&mfc, sizeof mfc);
+
+                       if (!banner_printed) {
+                               printf("\nMulticast Forwarding Cache\n"
+                                      " Origin          Group            "
+                                      " Packets In-Vif  Out-Vifs:Ttls\n");
+                               banner_printed = 1;
+                       }
+
+                       printf(" %-15.15s", routename(mfc.mfc_origin.s_addr));
+                       printf(" %-15.15s", routename(mfc.mfc_mcastgrp.s_addr));
+                       printf(" %9lu", mfc.mfc_pkt_cnt);
+                       printf("  %3d   ", mfc.mfc_parent);
+                       for (vifi = 0; vifi <= maxvif; vifi++) {
+                               if (mfc.mfc_ttls[vifi] > 0)
+                                       printf(" %u:%u", vifi, 
+                                              mfc.mfc_ttls[vifi]);
+                       }
+                       printf("\n");
+                       m = mfc.mfc_next;
+               }
+       }
+       if (!banner_printed)
+               printf("\nMulticast Routing Table is empty\n");
+
+       printf("\n");
+       nflag = saved_nflag;
+}
+
+
+void
+mrt_stats(mstaddr)
+       u_long mstaddr;
+{
+       struct mrtstat mrtstat;
+
+       if (mstaddr == 0) {
+               printf("No multicast routing compiled into this system.\n");
+               return;
+       }
+
+       kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
+       printf("multicast forwarding:\n");
+       printf(" %10lu multicast forwarding cache lookup%s\n",
+         mrtstat.mrts_mfc_lookups, plural(mrtstat.mrts_mfc_lookups));
+       printf(" %10lu multicast forwarding cache miss%s\n",
+         mrtstat.mrts_mfc_misses, plurales(mrtstat.mrts_mfc_misses));
+       printf(" %10lu upcall%s to mrouted\n",
+         mrtstat.mrts_upcalls, plural(mrtstat.mrts_upcalls));
+       printf(" %10lu upcall queue overflow%s\n",
+         mrtstat.mrts_upq_ovflw, plural(mrtstat.mrts_upq_ovflw));
+       printf(" %10lu upcall%s dropped due to full socket buffer\n",
+         mrtstat.mrts_upq_sockfull, plural(mrtstat.mrts_upq_sockfull));
+       printf(" %10lu cache cleanup%s\n",
+         mrtstat.mrts_cache_cleanups, plural(mrtstat.mrts_cache_cleanups));
+       printf(" %10lu datagram%s with no route for origin\n",
+         mrtstat.mrts_no_route, plural(mrtstat.mrts_no_route));
+       printf(" %10lu datagram%s arrived with bad tunneling\n",
+         mrtstat.mrts_bad_tunnel, plural(mrtstat.mrts_bad_tunnel));
+       printf(" %10lu datagram%s could not be tunneled\n",
+         mrtstat.mrts_cant_tunnel, plural(mrtstat.mrts_cant_tunnel));
+       printf(" %10lu datagram%s arrived on wrong interface\n",
+         mrtstat.mrts_wrong_if, plural(mrtstat.mrts_wrong_if));
+       printf(" %10lu datagram%s selectively dropped\n",
+         mrtstat.mrts_drop_sel, plural(mrtstat.mrts_drop_sel));
+       printf(" %10lu datagram%s dropped due to queue overflow\n",
+         mrtstat.mrts_q_overflow, plural(mrtstat.mrts_q_overflow));
+       printf(" %10lu datagram%s dropped for being too large\n",
+         mrtstat.mrts_pkt2large, plural(mrtstat.mrts_pkt2large));
+}
diff --git a/netstat.tproj/netstat.1 b/netstat.tproj/netstat.1
new file mode 100644 (file)
index 0000000..fc0d303
--- /dev/null
@@ -0,0 +1,289 @@
+.\" Copyright (c) 1983, 1990, 1992, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)netstat.1   8.8 (Berkeley) 4/18/94
+.\"
+.Dd April 18, 1994
+.Dt NETSTAT 1
+.Os BSD 4.2
+.Sh NAME
+.Nm netstat
+.Nd show network status
+.Sh SYNOPSIS
+.Nm netstat
+.Op Fl Aan
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Nm netstat
+.Op Fl dghimnrs
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Nm netstat
+.Op Fl dn
+.Op Fl I Ar interface
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar wait
+.Nm netstat
+.Op Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Sh DESCRIPTION
+The
+.Nm netstat
+command symbolically displays the contents of various network-related
+data structures.
+There are a number of output formats,
+depending on the options for the information presented.
+The first form of the command displays a list of active sockets for
+each protocol.
+The second form presents the contents of one of the other network
+data structures according to the option selected.
+Using the third form, with a
+.Ar wait
+interval specified,
+.Nm netstat
+will continuously display the information regarding packet
+traffic on the configured network interfaces.
+The fourth form displays statistics about the named protocol.
+.Pp
+The options have the following meaning:
+.Bl -tag -width flag
+.It Fl A
+With the default display,
+show the address of any protocol control blocks associated with sockets; used
+for debugging.
+.It Fl a
+With the default display,
+show the state of all sockets; normally sockets used by
+server processes are not shown.
+.It Fl d
+With either interface display (option
+.Fl i
+or an interval, as described below),
+show the number of dropped packets.
+.It Fl f Ar address_family 
+Limit statistics or address control block reports to those
+of the specified
+.Ar address family  .
+The following address families
+are recognized:
+.Ar inet  ,
+for
+.Dv AF_INET  ,
+.Ar ns ,
+for
+.Dv AF_NS  ,
+.Ar iso ,
+for
+.Dv AF_ISO ,
+and
+.Ar unix  ,
+for
+.Dv AF_UNIX  .
+.It Fl g
+Show information related to multicast (group address) routing.
+By default, show the IP Multicast virtual-interface and routing tables.
+If the
+.Fl s
+option is also present, show multicast routing statistics.
+.It Fl h
+Show the state of the
+.Tn IMP
+host table (obsolete).
+.It Fl I Ar interface 
+Show information about the specified interface;
+used with a
+.Ar wait
+interval as described below.
+.It Fl i
+Show the state of interfaces which have been auto-configured
+(interfaces statically configured into a system, but not
+located at boot time are not shown).
+If the
+.Fl a
+options is also present, multicast addresses currently in use are shown
+for each Ethernet interface and for each IP interface address.
+Multicast addresses are shown on separate lines following the interface
+address with which they are associated.
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl m
+Show statistics recorded by the memory management routines
+(the network manages a private pool of memory buffers).
+.It Fl N
+Extract the name list from the specified system instead of the default
+.Pa /vmunix .
+.It Fl n
+Show network addresses as numbers (normally
+.Nm netstat
+interprets addresses and attempts to display them
+symbolically).
+This option may be used with any of the display formats.
+.It Fl p Ar protocol 
+Show statistics about
+.Ar protocol  ,
+which is either a well-known name for a protocol or an alias for it.  Some
+protocol names and aliases are listed in the file
+.Pa /etc/protocols .
+A null response typically means that there are no interesting numbers to
+report.
+The program will complain if
+.Ar protocol
+is unknown or if there is no statistics routine for it.
+.It Fl s
+Show per-protocol statistics.
+If this option is repeated, counters with a value of zero are suppressed.
+.It Fl r
+Show the routing tables.
+When
+.Fl s
+is also present, show routing statistics instead.
+.It Fl w Ar wait
+Show network interface statistics at intervals of
+.Ar wait
+seconds.
+.El
+.Pp
+The default display, for active sockets, shows the local
+and remote addresses, send and receive queue sizes (in bytes), protocol,
+and the internal state of the protocol.
+Address formats are of the form ``host.port'' or ``network.port''
+if a socket's address specifies a network but no specific host address.
+When known the host and network addresses are displayed symbolically
+according to the data bases
+.Pa /etc/hosts
+and
+.Pa /etc/networks ,
+respectively.  If a symbolic name for an address is unknown, or if
+the
+.Fl n
+option is specified, the address is printed numerically, according
+to the address family.
+For more information regarding
+the Internet ``dot format,''
+refer to
+.Xr inet 3 ) .
+Unspecified,
+or ``wildcard'', addresses and ports appear as ``*''.
+.Pp
+The interface display provides a table of cumulative
+statistics regarding packets transferred, errors, and collisions.
+The network addresses of the interface
+and the maximum transmission unit (``mtu'') are also displayed.
+.Pp
+The routing table display indicates the available routes and
+their status.  Each route consists of a destination host or network
+and a gateway to use in forwarding packets.  The flags field shows
+a collection of information about the route stored as
+binary choices.  The individual flags are discussed in more
+detail in the
+.Xr route 8
+and
+.Xr route 4
+manual pages.
+The mapping between letters and flags is:
+.Bl -column XXXX RTF_BLACKHOLE
+1      RTF_PROTO2      Protocol specific routing flag #1 
+2      RTF_PROTO1      Protocol specific routing flag #2 
+B      RTF_BLACKHOLE   Just discard pkts (during updates) 
+C      RTF_CLONING     Generate new routes on use 
+D      RTF_DYNAMIC     Created dynamically (by redirect) 
+G      RTF_GATEWAY     Destination requires forwarding by intermediary
+H      RTF_HOST        Host entry (net otherwise) 
+L      RTF_LLINFO      Valid protocol to link address translation.
+M      RTF_MODIFIED    Modified dynamically (by redirect) 
+R      RTF_REJECT      Host or net unreachable 
+S      RTF_STATIC      Manually added 
+U      RTF_UP  Route usable 
+X      RTF_XRESOLVE    External daemon translates proto to link address
+.El
+.Pp
+Direct routes are created for each
+interface attached to the local host;
+the gateway field for such entries shows the address of the outgoing interface.
+The refcnt field gives the
+current number of active uses of the route.  Connection oriented
+protocols normally hold on to a single route for the duration of
+a connection while connectionless protocols obtain a route while sending
+to the same destination.
+The use field provides a count of the number of packets
+sent using that route.  The interface entry indicates the network
+interface utilized for the route.
+.Pp
+When
+.Nm netstat
+is invoked with the
+.Fl w
+option and a
+.Ar wait
+interval argument, it displays a running count of statistics related to
+network interfaces.
+An obsolescent version of this option used a numeric parameter
+with no option, and is currently supported for backward compatibility.
+This display consists of a column for the primary interface (the first
+interface found during autoconfiguration) and a column summarizing
+information for all interfaces.
+The primary interface may be replaced with another interface with the
+.Fl I
+option.
+The first line of each screen of information contains a summary since the
+system was last rebooted.  Subsequent lines of output show values
+accumulated over the preceding interval.
+.Sh SEE ALSO
+.Xr iostat 1 ,
+.Xr nfsstat 1 ,
+.Xr ps 1 ,
+.Xr vmstat 1 ,
+.Xr hosts 5 ,
+.Xr networks 5 ,
+.Xr protocols 5 ,
+.Xr services 5 ,
+.Xr trpt 8 ,
+.Xr trsp 8
+.Sh HISTORY
+The
+.Nm netstat
+command appeared in
+.Bx 4.2 .
+.\" .Sh FILES
+.\" .Bl -tag -width /dev/kmem -compact
+.\" .It Pa /vmunix
+.\" default kernel namelist
+.\" .It Pa /dev/kmem
+.\" default memory file
+.\" .El
+.Sh BUGS
+The notion of errors is ill-defined.
diff --git a/netstat.tproj/netstat.h b/netstat.tproj/netstat.h
new file mode 100644 (file)
index 0000000..8a70629
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993
+ *     Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)netstat.h   8.2 (Berkeley) 1/4/94
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+EXTERN int     Aflag;          /* show addresses of protocol control block */
+EXTERN int     aflag;          /* show all sockets (including servers) */
+EXTERN int     bflag;          /* show i/f total bytes in/out */
+EXTERN int     dflag;          /* show i/f dropped packets */
+EXTERN int     gflag;          /* show group (multicast) routing or stats */
+EXTERN int     iflag;          /* show static interfaces */
+EXTERN int     mflag;          /* show memory stats */
+EXTERN int     nflag;          /* show addresses numerically */
+EXTERN int     pflag;          /* show given protocol */
+EXTERN int     rflag;          /* show routing tables (or routing stats) */
+EXTERN int     sflag;          /* show protocol statistics */
+EXTERN int     tflag;          /* show i/f watchdog timers */
+
+EXTERN int     interval;       /* repeat interval for i/f stats */
+
+EXTERN char    *interface;     /* desired i/f for stats, or NULL for all i/fs */
+EXTERN int     unit;           /* unit number for above */
+
+EXTERN int     af;             /* address family */
+
+int    kread __P((u_long addr, char *buf, int size));
+char   *plural __P((int));
+char   *plurales __P((int));
+void   trimdomain __P((char *));
+
+void   protopr __P((u_long, char *));
+void   tcp_stats __P((u_long, char *));
+void   udp_stats __P((u_long, char *));
+void   ip_stats __P((u_long, char *));
+void   icmp_stats __P((u_long, char *));
+void   igmp_stats __P((u_long, char *));
+void   protopr __P((u_long, char *));
+
+void   mbpr __P((u_long));
+
+void   hostpr __P((u_long, u_long));
+void   impstats __P((u_long, u_long));
+
+void   intpr __P((int, u_long));
+
+void   pr_rthdr __P(());
+void   pr_family __P((int));
+void   rt_stats __P((u_long));
+char   *ipx_pnet __P((struct sockaddr *));
+char   *ipx_phost __P((struct sockaddr *));
+char   *ns_phost __P((struct sockaddr *));
+void   upHex __P((char *));
+
+char   *routename __P((u_long));
+char   *netname __P((u_long, u_long));
+char   *atalk_print __P((struct sockaddr *, int));
+char   *atalk_print2 __P((struct sockaddr *, struct sockaddr *, int));
+char   *ipx_print __P((struct sockaddr *));
+char   *ns_print __P((struct sockaddr *));
+void   routepr __P((u_long));
+
+void   ipxprotopr __P((u_long, char *));
+void   spx_stats __P((u_long, char *));
+void   ipx_stats __P((u_long, char *));
+void   ipxerr_stats __P((u_long, char *));
+
+void   nsprotopr __P((u_long, char *));
+void   spp_stats __P((u_long, char *));
+void   idp_stats __P((u_long, char *));
+void   nserr_stats __P((u_long, char *));
+
+void   atalkprotopr __P((u_long, char *));
+void   ddp_stats __P((u_long, char *));
+
+void   intpr __P((int, u_long));
+
+void   unixpr __P((void));
+
+void   esis_stats __P((u_long, char *));
+void   clnp_stats __P((u_long, char *));
+void   cltp_stats __P((u_long, char *));
+void   iso_protopr __P((u_long, char *));
+void   iso_protopr1 __P((u_long, int));
+void   tp_protopr __P((u_long, char *));
+void   tp_inproto __P((u_long));
+void   tp_stats __P((caddr_t, caddr_t));
+
+void   mroutepr __P((u_long, u_long));
+void   mrt_stats __P((u_long));
+
diff --git a/netstat.tproj/route.c b/netstat.tproj/route.c
new file mode 100644 (file)
index 0000000..84b945a
--- /dev/null
@@ -0,0 +1,918 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "From: @(#)route.c      8.6 (Berkeley) 4/28/95";
+#endif
+static const char rcsid[] =
+       "$Id: route.c,v 1.1.1.2 2000/01/11 01:48:53 wsanchez Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+
+#ifdef IPX
+#include <netipx/ipx.h>
+#include <netatalk/at.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#endif
+
+#include <sys/sysctl.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <time.h>
+#include "netstat.h"
+
+#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
+
+/*
+ * Definitions for showing gateway flags.
+ */
+struct bits {
+       u_long  b_mask;
+       char    b_val;
+} bits[] = {
+       { RTF_UP,       'U' },
+       { RTF_GATEWAY,  'G' },
+       { RTF_HOST,     'H' },
+       { RTF_REJECT,   'R' },
+       { RTF_DYNAMIC,  'D' },
+       { RTF_MODIFIED, 'M' },
+       { RTF_DONE,     'd' }, /* Completed -- for routing messages only */
+       { RTF_CLONING,  'C' },
+       { RTF_XRESOLVE, 'X' },
+       { RTF_LLINFO,   'L' },
+       { RTF_STATIC,   'S' },
+       { RTF_PROTO1,   '1' },
+       { RTF_PROTO2,   '2' },
+       { RTF_WASCLONED,'W' },
+       { RTF_PRCLONING,'c' },
+       { RTF_PROTO3,   '3' },
+       { RTF_BLACKHOLE,'B' },
+       { RTF_BROADCAST,'b' },
+       { 0 }
+};
+
+typedef union {
+       long    dummy;          /* Helps align structure. */
+       struct  sockaddr u_sa;
+       u_short u_data[128];
+} sa_u;
+
+static sa_u pt_u;
+
+int    do_rtent = 0;
+struct rtentry rtentry;
+struct radix_node rnode;
+struct radix_mask rmask;
+struct radix_node_head *rt_tables[AF_MAX+1];
+
+int    NewTree = 0;
+
+static struct sockaddr *kgetsa __P((struct sockaddr *));
+static void p_tree __P((struct radix_node *));
+static void p_rtnode __P((void));
+static void ntreestuff __P((void));
+static void np_rtentry __P((struct rt_msghdr *));
+static void p_sockaddr __P((struct sockaddr *, struct sockaddr *, int, int));
+static void p_flags __P((int, char *));
+static void p_rtentry __P((struct rtentry *));
+static u_long forgemask __P((u_long));
+static void domask __P((char *, u_long, u_long));
+
+/*
+ * Print routing tables.
+ */
+void
+routepr(rtree)
+       u_long rtree;
+{
+       struct radix_node_head *rnh, head;
+       int i;
+
+       printf("Routing tables\n");
+
+       if (Aflag == 0 && NewTree)
+               ntreestuff();
+       else {
+               if (rtree == 0) {
+                       printf("rt_tables: symbol not in namelist\n");
+                       return;
+               }
+
+               kget(rtree, rt_tables);
+               for (i = 0; i <= AF_MAX; i++) {
+                       if ((rnh = rt_tables[i]) == 0)
+                               continue;
+                       kget(rnh, head);
+                       if (i == AF_UNSPEC) {
+                               if (Aflag && af == 0) {
+                                       printf("Netmasks:\n");
+                                       p_tree(head.rnh_treetop);
+                               }
+                       } else if (af == AF_UNSPEC || af == i) {
+                               pr_family(i);
+                               do_rtent = 1;
+                               pr_rthdr();
+                               p_tree(head.rnh_treetop);
+                       }
+               }
+       }
+}
+
+/*
+ * Print address family header before a section of the routing table.
+ */
+void
+pr_family(af)
+       int af;
+{
+       char *afname;
+
+       switch (af) {
+       case AF_INET:
+               afname = "Internet";
+               break;
+
+#ifdef IPX
+       case AF_IPX:
+               afname = "IPX";
+               break;
+#endif
+
+#ifdef NS
+       case AF_NS:
+               afname = "XNS";
+               break;
+#endif
+       case AF_ISO:
+               afname = "ISO";
+               break;
+       case AF_APPLETALK:
+               afname = "AppleTalk";
+               break;
+       case AF_CCITT:
+               afname = "X.25";
+               break;
+       default:
+               afname = NULL;
+               break;
+       }
+       if (afname)
+               printf("\n%s:\n", afname);
+       else
+               printf("\nProtocol Family %d:\n", af);
+}
+
+/* column widths; each followed by one space */
+#define        WID_DST         18      /* width of destination column */
+#define        WID_GW          18      /* width of gateway column */
+
+/*
+ * Print header for routing table columns.
+ */
+void
+pr_rthdr()
+{
+       if (Aflag)
+               printf("%-8.8s ","Address");
+       printf("%-*.*s %-*.*s %-6.6s  %6.6s%8.8s  %8.8s %6s\n",
+               WID_DST, WID_DST, "Destination",
+               WID_GW, WID_GW, "Gateway",
+               "Flags", "Refs", "Use", "Netif", "Expire");
+}
+
+static struct sockaddr *
+kgetsa(dst)
+       register struct sockaddr *dst;
+{
+
+       kget(dst, pt_u.u_sa);
+       if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
+               kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
+       return (&pt_u.u_sa);
+}
+
+static void
+p_tree(rn)
+       struct radix_node *rn;
+{
+
+again:
+       kget(rn, rnode);
+       if (rnode.rn_b < 0) {
+               if (Aflag)
+                       printf("%-8.8lx ", (u_long)rn);
+               if (rnode.rn_flags & RNF_ROOT) {
+                       if (Aflag)
+                               printf("(root node)%s",
+                                   rnode.rn_dupedkey ? " =>\n" : "\n");
+               } else if (do_rtent) {
+                       kget(rn, rtentry);
+                       p_rtentry(&rtentry);
+                       if (Aflag)
+                               p_rtnode();
+               } else {
+                       p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
+                                  NULL, 0, 44);
+                       putchar('\n');
+               }
+               if ((rn = rnode.rn_dupedkey))
+                       goto again;
+       } else {
+               if (Aflag && do_rtent) {
+                       printf("%-8.8lx ", (u_long)rn);
+                       p_rtnode();
+               }
+               rn = rnode.rn_r;
+               p_tree(rnode.rn_l);
+               p_tree(rn);
+       }
+}
+
+char   nbuf[20];
+
+static void
+p_rtnode()
+{
+       struct radix_mask *rm = rnode.rn_mklist;
+
+       if (rnode.rn_b < 0) {
+               if (rnode.rn_mask) {
+                       printf("\t  mask ");
+                       p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
+                                  NULL, 0, -1);
+               } else if (rm == 0)
+                       return;
+       } else {
+               sprintf(nbuf, "(%d)", rnode.rn_b);
+               printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_l, (u_long)rnode.rn_r);
+       }
+       while (rm) {
+               kget(rm, rmask);
+               sprintf(nbuf, " %d refs, ", rmask.rm_refs);
+               printf(" mk = %8.8lx {(%d),%s",
+                       (u_long)rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " ");
+               if (rmask.rm_flags & RNF_NORMAL) {
+                       struct radix_node rnode_aux;
+                       printf(" <normal>, ");
+                       kget(rmask.rm_leaf, rnode_aux);
+                       p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
+                                   NULL, 0, -1);
+               } else
+                   p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
+                               NULL, 0, -1);
+               putchar('}');
+               if ((rm = rmask.rm_mklist))
+                       printf(" ->");
+       }
+       putchar('\n');
+}
+
+static void
+ntreestuff()
+{
+       size_t needed;
+       int mib[6];
+       char *buf, *next, *lim;
+       register struct rt_msghdr *rtm;
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;
+       mib[3] = 0;
+       mib[4] = NET_RT_DUMP;
+       mib[5] = 0;
+       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
+               err(1, "sysctl: net.route.0.0.dump estimate");
+       }
+
+       if ((buf = malloc(needed)) == 0) {
+               err(2, "malloc(%lu)", (unsigned long)needed);
+       }
+       if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+               err(1, "sysctl: net.route.0.0.dump");
+       }
+       lim  = buf + needed;
+       for (next = buf; next < lim; next += rtm->rtm_msglen) {
+               rtm = (struct rt_msghdr *)next;
+               np_rtentry(rtm);
+       }
+}
+
+static void
+np_rtentry(rtm)
+       register struct rt_msghdr *rtm;
+{
+       register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+#ifdef notdef
+       static int masks_done, banner_printed;
+#endif
+       static int old_af;
+       int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
+
+#ifdef notdef
+       /* for the moment, netmasks are skipped over */
+       if (!banner_printed) {
+               printf("Netmasks:\n");
+               banner_printed = 1;
+       }
+       if (masks_done == 0) {
+               if (rtm->rtm_addrs != RTA_DST ) {
+                       masks_done = 1;
+                       af = sa->sa_family;
+               }
+       } else
+#endif
+               af = sa->sa_family;
+       if (af != old_af) {
+               pr_family(af);
+               old_af = af;
+       }
+       if (rtm->rtm_addrs == RTA_DST)
+               p_sockaddr(sa, NULL, 0, 36);
+       else {
+               p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
+               if (sa->sa_len == 0)
+                       sa->sa_len = sizeof(long);
+               sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
+               p_sockaddr(sa, NULL, 0, 18);
+       }
+       p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
+       putchar('\n');
+}
+
+static void
+p_sockaddr(sa, mask, flags, width)
+       struct sockaddr *sa, *mask;
+       int flags, width;
+{
+       char workbuf[128], *cplim;
+       register char *cp = workbuf;
+
+       switch(sa->sa_family) {
+       case AF_INET:
+           {
+               register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+               if (sin->sin_addr.s_addr == INADDR_ANY)
+                       cp = "default";
+               else if (flags & RTF_HOST)
+                       cp = routename(sin->sin_addr.s_addr);
+               else if (mask)
+                       cp = netname(sin->sin_addr.s_addr,
+                                    ntohl(((struct sockaddr_in *)mask)
+                                          ->sin_addr.s_addr));
+               else
+                       cp = netname(sin->sin_addr.s_addr, 0L);
+               break;
+           }
+#ifdef IPX
+       case AF_IPX:
+           {
+               struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
+               if (ipx_nullnet(satoipx_addr(work)))
+                       cp = "default";
+               else
+                       cp = ipx_print(sa);
+               break;
+           }
+#endif
+
+#if 0
+       case AF_APPLETALK:
+           {
+               if (!(flags & RTF_HOST) && mask)
+                       cp = atalk_print2(sa,mask,9);
+               else
+                       cp = atalk_print(sa,11);
+               break;
+           }
+#endif
+
+#ifdef NS
+       case AF_NS:
+               cp = ns_print(sa);
+               break;
+#endif
+
+       case AF_LINK:
+           {
+               register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
+
+               if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
+                   sdl->sdl_slen == 0)
+                       (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
+               else
+                       switch (sdl->sdl_type) {
+
+                       case IFT_ETHER:
+                           {
+                               register int i;
+                               register u_char *lla = (u_char *)sdl->sdl_data +
+                                   sdl->sdl_nlen;
+
+                               cplim = "";
+                               for (i = 0; i < sdl->sdl_alen; i++, lla++) {
+                                       cp += sprintf(cp, "%s%x", cplim, *lla);
+                                       cplim = ":";
+                               }
+                               cp = workbuf;
+                               break;
+                           }
+
+                       default:
+                               cp = link_ntoa(sdl);
+                               break;
+                       }
+               break;
+           }
+
+       default:
+           {
+               register u_char *s = (u_char *)sa->sa_data, *slim;
+
+               slim =  sa->sa_len + (u_char *) sa;
+               cplim = cp + sizeof(workbuf) - 6;
+               cp += sprintf(cp, "(%d)", sa->sa_family);
+               while (s < slim && cp < cplim) {
+                       cp += sprintf(cp, " %02x", *s++);
+                       if (s < slim)
+                           cp += sprintf(cp, "%02x", *s++);
+               }
+               cp = workbuf;
+           }
+       }
+       if (width < 0 )
+               printf("%s ", cp);
+       else {
+               if (nflag)
+                       printf("%-*s ", width, cp);
+               else
+                       printf("%-*.*s ", width, width, cp);
+       }
+}
+
+static void
+p_flags(f, format)
+       register int f;
+       char *format;
+{
+       char name[33], *flags;
+       register struct bits *p = bits;
+
+       for (flags = name; p->b_mask; p++)
+               if (p->b_mask & f)
+                       *flags++ = p->b_val;
+       *flags = '\0';
+       printf(format, name);
+}
+
+static void
+p_rtentry(rt)
+       register struct rtentry *rt;
+{
+       static struct ifnet ifnet, *lastif;
+       static char name[16];
+       static char prettyname[9];
+       struct sockaddr *sa;
+       sa_u addr, mask;
+
+       /*
+        * Don't print protocol-cloned routes unless -a.
+        */
+       if (rt->rt_parent && !aflag)
+               return;
+
+       bzero(&addr, sizeof(addr));
+       if ((sa = kgetsa(rt_key(rt))))
+               bcopy(sa, &addr, sa->sa_len);
+       bzero(&mask, sizeof(mask));
+       if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
+               bcopy(sa, &mask, sa->sa_len);
+       p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, WID_DST);
+       p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW);
+       p_flags(rt->rt_flags, "%-6.6s ");
+       printf("%6d %8ld ", rt->rt_refcnt, rt->rt_use);
+       if (rt->rt_ifp) {
+               if (rt->rt_ifp != lastif) {
+                       kget(rt->rt_ifp, ifnet);
+                       kread((u_long)ifnet.if_name, name, 16);
+                       lastif = rt->rt_ifp;
+                       snprintf(prettyname, sizeof prettyname,
+                                "%.6s%d", name, ifnet.if_unit);
+               }
+               printf("%8.8s", prettyname);
+               if (rt->rt_rmx.rmx_expire) {
+                       time_t expire_time;
+
+                       if ((expire_time =
+                           rt->rt_rmx.rmx_expire - time((time_t *)0)) > 0)
+                               printf(" %6d%s", (int)expire_time,
+                                   rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
+               } else if (rt->rt_nodes[0].rn_dupedkey) {
+                       printf(" =>");
+               }
+
+       }
+       putchar('\n');
+}
+
+char *
+routename(in)
+       u_long in;
+{
+       register char *cp;
+       static char line[MAXHOSTNAMELEN + 1];
+       struct hostent *hp;
+
+       cp = 0;
+       if (!nflag) {
+               hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
+                       AF_INET);
+               if (hp) {
+                       cp = hp->h_name;
+                       trimdomain(cp);
+               }
+       }
+       if (cp) {
+               strncpy(line, cp, sizeof(line) - 1);
+               line[sizeof(line) - 1] = '\0';
+       } else {
+#define C(x)   ((x) & 0xff)
+               in = ntohl(in);
+               sprintf(line, "%lu.%lu.%lu.%lu",
+                   C(in >> 24), C(in >> 16), C(in >> 8), C(in));
+       }
+       return (line);
+}
+
+static u_long
+forgemask(a)
+       u_long a;
+{
+       u_long m;
+
+       if (IN_CLASSA(a))
+               m = IN_CLASSA_NET;
+       else if (IN_CLASSB(a))
+               m = IN_CLASSB_NET;
+       else
+               m = IN_CLASSC_NET;
+       return (m);
+}
+
+static void
+domask(dst, addr, mask)
+       char *dst;
+       u_long addr, mask;
+{
+       register int b, i;
+
+       if (!mask || (forgemask(addr) == mask)) {
+               *dst = '\0';
+               return;
+       }
+       i = 0;
+       for (b = 0; b < 32; b++)
+               if (mask & (1 << b)) {
+                       register int bb;
+
+                       i = b;
+                       for (bb = b+1; bb < 32; bb++)
+                               if (!(mask & (1 << bb))) {
+                                       i = -1; /* noncontig */
+                                       break;
+                               }
+                       break;
+               }
+       if (i == -1)
+               sprintf(dst, "&0x%lx", mask);
+       else
+               sprintf(dst, "/%d", 32-i);
+}
+
+/*
+ * Return the name of the network whose address is given.
+ * The address is assumed to be that of a net or subnet, not a host.
+ */
+char *
+netname(in, mask)
+       u_long in, mask;
+{
+       char *cp = 0;
+       static char line[MAXHOSTNAMELEN + 1];
+       struct netent *np = 0;
+       u_long net, omask, dmask;
+       register u_long i;
+
+       i = ntohl(in);
+       omask = mask;
+       if (!nflag && i) {
+               dmask = forgemask(i);
+               net = i & dmask;
+               if (!(np = getnetbyaddr(i, AF_INET)) && net != i)
+                       np = getnetbyaddr(net, AF_INET);
+               if (np) {
+                       cp = np->n_name;
+                       trimdomain(cp);
+               }
+       }
+       if (cp)
+               strncpy(line, cp, sizeof(line) - 1);
+       else if ((i & 0xffffff) == 0)
+               sprintf(line, "%lu", C(i >> 24));
+       else if ((i & 0xffff) == 0)
+               sprintf(line, "%lu.%lu", C(i >> 24) , C(i >> 16));
+       else if ((i & 0xff) == 0)
+               sprintf(line, "%lu.%lu.%lu", C(i >> 24), C(i >> 16), C(i >> 8));
+       else
+               sprintf(line, "%lu.%lu.%lu.%lu", C(i >> 24),
+                       C(i >> 16), C(i >> 8), C(i));
+       domask(line+strlen(line), i, omask);
+       return (line);
+}
+
+/*
+ * Print routing statistics
+ */
+void
+rt_stats(off)
+       u_long off;
+{
+       struct rtstat rtstat;
+
+       if (off == 0) {
+               printf("rtstat: symbol not in namelist\n");
+               return;
+       }
+       kread(off, (char *)&rtstat, sizeof (rtstat));
+       printf("routing:\n");
+       printf("\t%u bad routing redirect%s\n",
+               rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
+       printf("\t%u dynamically created route%s\n",
+               rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
+       printf("\t%u new gateway%s due to redirects\n",
+               rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
+       printf("\t%u destination%s found unreachable\n",
+               rtstat.rts_unreach, plural(rtstat.rts_unreach));
+       printf("\t%u use%s of a wildcard route\n",
+               rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
+}
+
+#ifdef IPX
+
+char *
+ipx_print(sa)
+       register struct sockaddr *sa;
+{
+       u_short port;
+       struct servent *sp = 0;
+       char *net = "", *host = "";
+       register char *p;
+       register u_char *q;
+       struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
+       static char mybuf[50];
+       char cport[10], chost[15], cnet[15];
+
+       port = ntohs(work.x_port);
+
+       if (ipx_nullnet(work) && ipx_nullhost(work)) {
+
+               if (port) {
+                       if (sp)
+                               sprintf(mybuf, "*.%s", sp->s_name);
+                       else
+                               sprintf(mybuf, "*.%x", port);
+               } else
+                       sprintf(mybuf, "*.*");
+
+               return (mybuf);
+       }
+
+       if (ipx_wildnet(work))
+               net = "any";
+       else if (ipx_nullnet(work))
+               net = "*";
+       else {
+               q = work.x_net.c_net;
+               sprintf(cnet, "%02x%02x%02x%02x",
+                       q[0], q[1], q[2], q[3]);
+               for (p = cnet; *p == '0' && p < cnet + 8; p++)
+                       continue;
+               net = p;
+       }
+
+       if (ipx_wildhost(work))
+               host = "any";
+       else if (ipx_nullhost(work))
+               host = "*";
+       else {
+               q = work.x_host.c_host;
+               sprintf(chost, "%02x%02x%02x%02x%02x%02x",
+                       q[0], q[1], q[2], q[3], q[4], q[5]);
+               for (p = chost; *p == '0' && p < chost + 12; p++)
+                       continue;
+               host = p;
+       }
+
+       if (port) {
+               if (strcmp(host, "*") == 0)
+                       host = "";
+               if (sp) 
+                       snprintf(cport, sizeof(cport),
+                               "%s%s", *host ? "." : "", sp->s_name);
+               else    
+                       snprintf(cport, sizeof(cport),
+                               "%s%x", *host ? "." : "", port);
+       } else
+               *cport = 0;
+
+       snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport);
+       return(mybuf);
+}
+
+char *
+ipx_phost(sa)
+       struct sockaddr *sa;
+{
+       register struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa;
+       struct sockaddr_ipx work;
+       static union ipx_net ipx_zeronet;
+       char *p;
+       struct ipx_addr in;
+
+       work = *sipx;
+       in = work.sipx_addr;
+
+       work.sipx_addr.x_port = 0;
+       work.sipx_addr.x_net = ipx_zeronet;
+       p = ipx_print((struct sockaddr *)&work);
+       if (strncmp("*.", p, 2) == 0) p += 2;
+
+       return(p);
+}
+#endif
+
+#ifdef NS
+short ns_nullh[] = {0,0,0};
+short ns_bh[] = {-1,-1,-1};
+
+char *
+ns_print(sa)
+       register struct sockaddr *sa;
+{
+       register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa;
+       struct ns_addr work;
+       union { union ns_net net_e; u_long long_e; } net;
+       u_short port;
+       static char mybuf[50], cport[10], chost[25];
+       char *host = "";
+       register char *p; register u_char *q;
+
+       work = sns->sns_addr;
+       port = ntohs(work.x_port);
+       work.x_port = 0;
+       net.net_e  = work.x_net;
+       if (ns_nullhost(work) && net.long_e == 0) {
+               if (port ) {
+                       sprintf(mybuf, "*.%xH", port);
+                       upHex(mybuf);
+               } else
+                       sprintf(mybuf, "*.*");
+               return (mybuf);
+       }
+
+       if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
+               host = "any";
+       } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
+               host = "*";
+       } else {
+               q = work.x_host.c_host;
+               sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
+                       q[0], q[1], q[2], q[3], q[4], q[5]);
+               for (p = chost; *p == '0' && p < chost + 12; p++)
+                       continue;
+               host = p;
+       }
+       if (port)
+               sprintf(cport, ".%xH", htons(port));
+       else
+               *cport = 0;
+
+       sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
+       upHex(mybuf);
+       return(mybuf);
+}
+
+char *
+ns_phost(sa)
+       struct sockaddr *sa;
+{
+       register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa;
+       struct sockaddr_ns work;
+       static union ns_net ns_zeronet;
+       char *p;
+
+       work = *sns;
+       work.sns_addr.x_port = 0;
+       work.sns_addr.x_net = ns_zeronet;
+
+       p = ns_print((struct sockaddr *)&work);
+       if (strncmp("0H.", p, 3) == 0)
+               p += 3;
+       return(p);
+}
+#endif
+
+void
+upHex(p0)
+       char *p0;
+{
+       register char *p = p0;
+
+       for (; *p; p++)
+               switch (*p) {
+
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+                       *p += ('A' - 'a');
+                       break;
+               }
+}
diff --git a/netstat.tproj/tp_astring.c b/netstat.tproj/tp_astring.c
new file mode 100644 (file)
index 0000000..af08ceb
--- /dev/null
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)tp_astring.c        8.1 (Berkeley) 6/10/93
+ */
+
+char *tp_sstring[] = {
+"ST_ERROR(0x0)",
+"TP_CLOSED(0x1)",
+"TP_CRSENT(0x2)",
+"TP_AKWAIT(0x3)",
+"TP_OPEN(0x4)",
+"TP_CLOSING(0x5)",
+"TP_REFWAIT(0x6)",
+"TP_LISTENING(0x7)",
+"TP_CONFIRMING(0x8)",
+};
+
+char *tp_estring[] = {
+"TM_inact(0x0)",
+"TM_retrans(0x1)",
+"TM_sendack(0x2)",
+"TM_notused(0x3)",
+"TM_reference(0x4)",
+"TM_data_retrans(0x5)",
+"ER_TPDU(0x6)",
+"CR_TPDU(0x7)",
+"DR_TPDU(0x8)",
+"DC_TPDU(0x9)",
+"CC_TPDU(0xa)",
+"AK_TPDU(0xb)",
+"DT_TPDU(0xc)",
+"XPD_TPDU(0xd)",
+"XAK_TPDU(0xe)",
+"T_CONN_req(0xf)",
+"T_DISC_req(0x10)",
+"T_LISTEN_req(0x11)",
+"T_DATA_req(0x12)",
+"T_XPD_req(0x13)",
+"T_USR_rcvd(0x14)",
+"T_USR_Xrcvd(0x15)",
+"T_DETACH(0x16)",
+"T_NETRESET(0x17)",
+"T_ACPT_req(0x18)",
+};
diff --git a/netstat.tproj/unix.c b/netstat.tproj/unix.c
new file mode 100644 (file)
index 0000000..c61c855
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)unix.c     8.1 (Berkeley) 6/6/93";
+#endif
+static const char rcsid[] =
+       "$Id: unix.c,v 1.1.1.2 2000/01/11 01:48:53 wsanchez Exp $";
+#endif /* not lint */
+
+/*
+ * Display protocol blocks in the unix domain.
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <kvm.h>
+#include "netstat.h"
+
+static void unixdomainpr __P((struct xunpcb *, struct xsocket *));
+
+static const char *const socktype[] =
+    { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
+
+void
+unixpr()
+{
+       char    *buf;
+       int     type;
+       size_t  len;
+       struct  xsocket *so;
+       struct  xunpgen *xug, *oxug;
+       struct  xunpcb *xunp;
+       char mibvar[sizeof "net.local.seqpacket.pcblist"];
+
+       for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
+               sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+
+               len = 0;
+               if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+                       if (errno != ENOENT)
+                               warn("sysctl: %s", mibvar);
+                       continue;
+               }
+               if ((buf = malloc(len)) == 0) {
+                       warn("malloc %lu bytes", (u_long)len);
+                       return;
+               }
+               if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+                       warn("sysctl: %s", mibvar);
+                       free(buf);
+                       return;
+               }
+
+               oxug = xug = (struct xunpgen *)buf;
+               for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
+                    xug->xug_len > sizeof(struct xunpgen);
+                    xug = (struct xunpgen *)((char *)xug + xug->xug_len)) {
+                       xunp = (struct xunpcb *)xug;
+                       so = &xunp->xu_socket;
+
+                       /* Ignore PCBs which were freed during copyout. */
+                       if (xunp->xu_unp.unp_gencnt > oxug->xug_gen)
+                               continue;
+                       unixdomainpr(xunp, so);
+               }
+               if (xug != oxug && xug->xug_gen != oxug->xug_gen) {
+                       if (oxug->xug_count > xug->xug_count) {
+                               printf("Some %s sockets may have been deleted.\n",
+                                      socktype[type]);
+                       } else if (oxug->xug_count < xug->xug_count) {
+                               printf("Some %s sockets may have been created.\n",
+                              socktype[type]);
+                       } else {
+                               printf("Some %s sockets may have been created or deleted",
+                              socktype[type]);
+                       }
+               }
+               free(buf);
+       }
+}
+
+static void
+unixdomainpr(xunp, so)
+       struct xunpcb *xunp;
+       struct xsocket *so;
+{
+       struct unpcb *unp;
+       struct sockaddr_un *sa;
+       static int first = 1;
+
+       unp = &xunp->xu_unp;
+       if (unp->unp_addr)
+               sa = &xunp->xu_addr;
+       else
+               sa = (struct sockaddr_un *)0;
+
+       if (first) {
+               printf("Active LOCAL (UNIX) domain sockets\n");
+               printf(
+"%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr\n",
+                   "Address", "Type", "Recv-Q", "Send-Q",
+                   "Inode", "Conn", "Refs", "Nextref");
+               first = 0;
+       }
+       printf("%8lx %-6.6s %6ld %6ld %8lx %8lx %8lx %8lx",
+              (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc,
+              so->so_snd.sb_cc,
+              (long)unp->unp_vnode, (long)unp->unp_conn,
+              (long)unp->unp_refs.lh_first, (long)unp->unp_reflink.le_next);
+       if (sa)
+               printf(" %.*s",
+                   (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)),
+                   sa->sun_path);
+       putchar('\n');
+}
diff --git a/newclient.tproj/Makefile b/newclient.tproj/Makefile
new file mode 100644 (file)
index 0000000..e822c95
--- /dev/null
@@ -0,0 +1,36 @@
+#
+#  Stubbed Legacy Makefile for the newclient script
+#
+
+NAME = newclient
+
+OTHERSRCS = Makefile Makefile.preamble newclient.csh
+
+MAKEFILEDIR = $(MAKEFILEPATH)/project
+MAKEFILE = common.make
+
+# INSTALL is already set to "install -S"
+XINSTALL = install
+
+INSTALLDIR=/usr/sbin
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
+
+all project $(NAME):
+
+install:
+       @dstdir=$(DSTROOT)`grep NEXTSTEP_INSTALLDIR PB.project | sed 's/.*= \(.*\);.*/\1/'`; \
+       if [ ! -d $$dstdir ]; then \
+           $(MKDIRS) $$dstdir; \
+       fi; \
+       $(RM) -f $$dstdir/$(NAME); \
+       echo    $(XINSTALL) -c -o $(INSTALL_AS_USER) -g $(INSTALL_AS_GROUP) \
+               -m 555 newclient.csh $$dstdir/$(NAME); \
+       $(XINSTALL) -c -o $(INSTALL_AS_USER) -g $(INSTALL_AS_GROUP) \
+               -m 555 newclient.csh $$dstdir/$(NAME)
diff --git a/newclient.tproj/Makefile.preamble b/newclient.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..fe326e5
--- /dev/null
@@ -0,0 +1 @@
+-include ../Makefile.include
diff --git a/newclient.tproj/PB.project b/newclient.tproj/PB.project
new file mode 100644 (file)
index 0000000..08d2bf1
--- /dev/null
@@ -0,0 +1,34 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (); 
+        OTHER_SOURCES = (Makefile, Makefile.preamble, newclient.csh); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = newclient; 
+    PROJECTTYPE = Legacy; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/newclient.tproj/newclient.csh b/newclient.tproj/newclient.csh
new file mode 100644 (file)
index 0000000..af24796
--- /dev/null
@@ -0,0 +1,233 @@
+#! /bin/csh -f
+##
+# Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+# Reserved.  This file contains Original Code and/or Modifications of
+# Original Code as defined in and that are subject to the Apple Public
+# Source License Version 1.0 (the 'License').  You may not use this file
+# except in compliance with the License.  Please obtain a copy of the
+# License at http://www.apple.com/publicsource and read it before using
+# this file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+# License for the specific language governing rights and limitations
+# under the License."
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+#
+# newclient
+#
+# NetBoot client building script.
+#
+# Copyright (c) 1988, NeXT, Inc.
+#
+# Usage:
+#      "newclient -p DISKTYPE TEMPLATE DEST" Standalone Private
+#      "newclient [-s SERVER] CLIENT-1 ... CLIENT-n" Clients
+#
+
+#
+# Constants
+#
+set path=(/bin /usr/bin /usr/ucb /usr/etc /etc)
+set TESTDIR
+set CLIENTDIR=${TESTDIR}/clients
+set template=${TESTDIR}/usr/template/client
+set HOSTFILE=${TESTDIR}/etc/hosts
+set BOOTPTAB=${TESTDIR}/etc/bootptab
+
+# We are the default server
+set server=`hostname`
+
+# Are we root?
+if ( `whoami` != root ) then
+       echo "You must be root to run $0"
+       exit(1)
+endif
+
+# Preliminary argument checkout
+if ( $#argv < 1 ) then
+       goto usage
+endif
+
+# Switches must be at argv[1]
+foreach arg ( $argv[2-] )
+       if ( x$arg =~ x-* ) then
+               goto usage
+       endif
+end
+
+# Parse the switches
+if ( $argv[1] == -p || $argv[1] == -P ) then
+       if ( $#argv != 4 ) then
+               goto usage
+       endif
+       set PrivateMode
+       set disktype=$argv[2]
+       set template=$argv[3]
+       set dest=$argv[4]
+       if ( $argv[1] == -P ) then
+               set swapsize=1b
+       else
+               set swapsize=16m
+       endif
+
+       # Check that the disk type is valid
+       if ( ! -e $template/etc/fstab.$disktype ) then
+               echo "Unknown disk type" $disktype
+               exit(1)
+       endif
+else if ( $argv[1] == -s ) then
+       if ( $#argv < 3 ) then
+               goto usage
+       endif
+       set server=$argv[2]
+       shift
+       shift
+else if ( $argv[1] =~ -* ) then
+       goto usage
+endif
+
+# Make sure we have a template to work with
+if ( ! -d $template ) then
+       echo "New client template $template does not exist"
+       exit(1)
+endif
+
+# Process the private partition if that is the mode we are in.
+if ( $?PrivateMode ) then
+       if ( -e $dest ) then
+               echo "$dest already exists"
+               exit(1)
+       endif
+
+       # Create the destination directory
+       echo -n "Creating ${dest}..."
+       mkdir $dest
+       chmod 775 $dest
+       chown root.staff $dest
+       if ( $status != 0 ) then
+               echo "failed"
+               exit(1)
+       endif
+       echo "[OK]"
+
+       # Copy the template into it
+       echo -n "Copying ${template} into ${dest}..."
+       (cd $template; tar cf - .)|(cd $dest; tar xpBf -)
+       echo "[OK]"
+
+       # Make the device files
+       echo -n "Making devices in ${dest}/dev..."
+       (cd ${dest}/dev; /usr/etc/MAKEDEV NeXT)
+       echo "[OK]"
+
+       # Customize the fstab file
+       echo -n "Installing fstab.$disktype as ${dest}/etc/fstab..."
+       cp -p $dest/etc/fstab.${disktype} $dest/etc/fstab
+       if ( $status != 0 ) then
+               echo "failed"
+               exit(1)
+       endif
+       echo "[OK]"
+
+       # Touch the first 16 Meg of the swapfile
+       echo -n "Preallocating swapfile blocks..."
+       (cd ${dest}/vm; /bin/rm -f swapfile; /usr/etc/mkfile $swapsize swapfile)
+       echo "[OK]"
+
+       exit(0)
+endif
+
+#
+# If we get here, then we are building a list of clients
+#
+
+echo $argv[*]
+foreach client ( $argv[*] )
+       if ( $server == localhost ) then
+               echo "This machine can't be a server until it is given a hostname"
+               exit(1)
+       endif
+       set dest=$CLIENTDIR/$client
+
+       if (! -f /private/tftpboot/mach) then
+               echo Installing /private/tftpboot/mach
+               cp -p /mach /private/tftpboot/mach
+       endif
+       if (! -f /private/tftpboot/boot) then
+               echo Installing /private/tftpboot/boot
+               cp -p /usr/standalone/boot /private/tftpboot/boot
+       endif
+
+       # Check for already existing client directory
+       if ( -e $dest ) then
+               echo $dest already exists
+               continue
+       endif
+
+       # Create the destination directory
+       echo -n "Creating $dest..."
+       mkdir -p -m $dest
+       chown root:staff $dest
+       if ( $status != 0 ) then
+               echo "failed"
+               exit(1)
+       endif
+       echo "[OK]"
+
+       # Copy the template into it.
+       echo -n "Copying $template into ${dest}..."
+       (cd $template; tar cf - .)|(cd $dest; tar xpBf -)
+       echo "[OK]"
+
+       # Make the device files
+       echo -n "Making devices in ${dest}/dev..."
+       (cd $dest/dev; /usr/etc/MAKEDEV NeXT)
+       echo "[OK]"
+
+       # Customize the fstab file
+       echo -n "Installing fstab.client as ${dest}/etc/fstab..."
+       cp -p $dest/etc/fstab.client $dest/etc/fstab
+       sed -e "s/SERVER/$server/g" -e "s/CLIENT/$client/g" $dest/etc/fstab.client > $dest/etc/fstab
+       if ( $status != 0 ) then
+               echo $failed
+               exit(1)
+       endif
+       echo "[OK]"
+
+       # Set up a symbolic link to the kernel
+       
+       if (-f ${dest}/tftpboot/mach) then
+               echo -n "Removing ${dest}/tftpboot/mach "
+               rm ${dest}/tftpboot/mach
+               echo "[OK]"
+       endif
+               
+       echo -n "Linking /tftpboot/mach to /sdmach "
+       ln -s /sdmach ${dest}/tftpboot/mach
+       echo "[OK]"
+
+       # Touch the first 16 Meg of the swapfile
+       echo -n "Creating swapfile..."
+       (cd ${dest}/vm; /bin/rm -f swapfile; /usr/etc/mkfile 8k swapfile)
+       echo "[OK]"
+
+end
+
+exit(0)
+
+usage:
+       echo "Usage: $0 -p DISKTYPE TEMPLATE DEST"
+       echo "       $0 [-s SERVER] CLIENT CLIENT ..."
+       exit(1)
+
+
diff --git a/nfsd.tproj/Makefile b/nfsd.tproj/Makefile
new file mode 100644 (file)
index 0000000..a765f04
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = nfsd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = nfsd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist nfsd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DNFS -DMACH_USER_API
+WINDOWS_PB_CFLAGS = -DNFS -DMACH_USER_API
+PDO_UNIX_PB_CFLAGS = -DNFS -DMACH_USER_API
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/nfsd.tproj/Makefile.dist b/nfsd.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..35d0d0e
--- /dev/null
@@ -0,0 +1,9 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  nfsd
+CFLAGS+=-DNFS
+MAN8=  nfsd.0
+DPADD= ${LIBRPC}
+LDADD= -lrpc
+
+.include <bsd.prog.mk>
diff --git a/nfsd.tproj/Makefile.preamble b/nfsd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/nfsd.tproj/PB.project b/nfsd.tproj/PB.project
new file mode 100644 (file)
index 0000000..f314b1d
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (nfsd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, nfsd.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = nfsd; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = nfsd; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = nfsd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = nfsd; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/nfsd.tproj/nfsd.8 b/nfsd.tproj/nfsd.8
new file mode 100644 (file)
index 0000000..e98aa13
--- /dev/null
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)nfsd.8      8.4 (Berkeley) 3/29/95
+.\"
+.Dd March 29, 1995
+.Dt NFSD 8
+.Os
+.Sh NAME
+.Nm nfsd
+.Nd remote
+.Tn NFS
+server
+.Sh SYNOPSIS
+.Nm nfsd
+.Op Fl rut
+.Op Fl n Ar num_servers
+.Sh DESCRIPTION
+.Nm Nfsd
+runs on a server machine to service
+.Tn NFS
+requests from client machines.
+At least one
+.Nm nfsd
+must be running for a machine to operate as a server.
+.Pp
+Unless otherwise specified, four servers for
+.Tn UDP
+transport are started.
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl r
+Register the
+.Tn NFS
+service with
+.Xr portmap 8
+without creating any servers.
+This option can be used along with the
+.Fl u
+or
+.Fl t
+options to re-register NFS if the portmap server is restarted.
+.It Fl n
+Specifies how many servers to create.
+.It Fl t
+Serve
+.Tn TCP NFS
+clients.
+.It Fl u
+Serve
+.Tn UDP NFS
+clients.
+.El
+.Pp
+For example, 
+.Dq Li "nfsd -u -t 6"
+serves
+.Tn UDP
+and
+.Tn TCP
+transports using six daemons.
+.Pp
+A server should run enough daemons to handle
+the maximum level of concurrency from its clients,
+typically four to six.
+.Pp
+.Nm Nfsd
+listens for service requests at the port indicated in the
+.Tn NFS
+server specification; see
+.%T "Network File System Protocol Specification" ,
+RFC1094 and
+.%T "NFS: Network File System Version 3 Protocol Specification" .
+.Pp
+The
+.Nm nfsd
+utility exits 0 on success, and >0 if an error occurs.
+.Sh SEE ALSO
+.Xr nfsstat 1 ,
+.Xr nfssvc 2 ,
+.Xr mountd 8 ,
+.Xr portmap 8
+.Sh HISTORY
+The
+.Nm nfsd
+utility first appeared in 4.4BSD.
diff --git a/nfsd.tproj/nfsd.c b/nfsd.tproj/nfsd.c
new file mode 100644 (file)
index 0000000..1c5acec
--- /dev/null
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/syslog.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+
+#ifdef ISO
+#include <netiso/iso.h>
+#endif
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+
+#ifdef NFSKERB
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+/* Global defs */
+#ifdef DEBUG
+#define        syslog(e, s)    fprintf(stderr,(s))
+int    debug = 1;
+#else
+int    debug = 0;
+#endif
+
+struct nfsd_srvargs nsd;
+char   **Argv = NULL;          /* pointer to argument vector */
+char   *LastArg = NULL;        /* end of argv */
+
+#ifdef NFSKERB
+char           lnam[ANAME_SZ];
+KTEXT_ST       kt;
+AUTH_DAT       kauth;
+char           inst[INST_SZ];
+struct nfsrpc_fullblock kin, kout;
+struct nfsrpc_fullverf kverf;
+NFSKERBKEY_T   kivec;
+struct timeval ktv;
+NFSKERBKEYSCHED_T kerb_keysched;
+#endif
+
+void   nonfs __P((int));
+void   reapchild __P((int));
+void   setproctitle __P((char *));
+void   usage __P((void));
+
+/*
+ * Nfs server daemon mostly just a user context for nfssvc()
+ *
+ * 1 - do file descriptor and signal cleanup
+ * 2 - fork the nfsd(s)
+ * 3 - create server socket(s)
+ * 4 - register socket with portmap
+ *
+ * For connectionless protocols, just pass the socket into the kernel via.
+ * nfssvc().
+ * For connection based sockets, loop doing accepts. When you get a new
+ * socket from accept, pass the msgsock into the kernel via. nfssvc().
+ * The arguments are:
+ *     -c - support iso cltp clients
+ *     -r - reregister with portmapper
+ *     -t - support tcp nfs clients
+ *     -u - support udp nfs clients
+ * followed by "n" which is the number of nfsds' to fork off
+ */
+int
+main(argc, argv, envp)
+       int argc;
+       char *argv[], *envp[];
+{
+       extern int optind;
+       struct group *grp;
+       struct nfsd_args nfsdargs;
+       struct passwd *pwd;
+       struct ucred *cr;
+       struct sockaddr_in inetaddr, inetpeer;
+#ifdef ISO
+       struct sockaddr_iso isoaddr, isopeer;
+#endif
+       struct timeval ktv;
+       fd_set ready, sockbits;
+       int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
+       int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
+       int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
+       char *cp, **cpp;
+
+       /* Save start and extent of argv for setproctitle. */
+       Argv = argv;
+       if (envp == 0 || *envp == 0)
+               envp = argv;
+       while (*envp)
+               envp++;
+       LastArg = envp[-1] + strlen(envp[-1]);
+
+#define        MAXNFSDCNT      20
+#define        DEFNFSDCNT       4
+       nfsdcnt = DEFNFSDCNT;
+       cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
+       tpipflag = udpflag = 0;
+#ifdef ISO
+#define        GETOPT  "cn:rtu"
+#define        USAGE   "[-crtu] [-n num_servers]"
+#else
+#define        GETOPT  "n:rtu"
+#define        USAGE   "[-rtu] [-n num_servers]"
+#endif
+       while ((ch = getopt(argc, argv, GETOPT)) != EOF)
+               switch (ch) {
+               case 'n':
+                       nfsdcnt = atoi(optarg);
+                       if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
+                               warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
+                               nfsdcnt = DEFNFSDCNT;
+                       }
+                       break;
+               case 'r':
+                       reregister = 1;
+                       break;
+               case 't':
+                       tcpflag = 1;
+                       break;
+               case 'u':
+                       udpflag = 1;
+                       break;
+#ifdef ISO
+               case 'c':
+                       cltpflag = 1;
+                       break;
+#ifdef notyet
+               case 'i':
+                       tp4cnt = 1;
+                       break;
+               case 'p':
+                       tpipcnt = 1;
+                       break;
+#endif /* notyet */
+#endif /* ISO */
+               default:
+               case '?':
+                       usage();
+               };
+       argv += optind;
+       argc -= optind;
+
+       /*
+        * XXX
+        * Backward compatibility, trailing number is the count of daemons.
+        */
+       if (argc > 1)
+               usage();
+       if (argc == 1) {
+               nfsdcnt = atoi(argv[0]);
+               if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
+                       warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
+                       nfsdcnt = DEFNFSDCNT;
+               }
+       }
+
+       if (debug == 0) {
+               daemon(0, 0);
+               (void)signal(SIGHUP, SIG_IGN);
+               (void)signal(SIGINT, SIG_IGN);
+               (void)signal(SIGQUIT, SIG_IGN);
+               (void)signal(SIGSYS, nonfs);
+               (void)signal(SIGTERM, SIG_IGN);
+       }
+       (void)signal(SIGCHLD, reapchild);
+
+       if (reregister) {
+               if (udpflag &&
+                   (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
+                    !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
+                       err(1, "can't register with portmap for UDP.");
+               if (tcpflag &&
+                   (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
+                    !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
+                       err(1, "can't register with portmap for TCP.");
+               exit(0);
+       }
+       openlog("nfsd:", LOG_PID, LOG_DAEMON);
+
+       for (i = 0; i < nfsdcnt; i++) {
+               switch (fork()) {
+               case -1:
+                       syslog(LOG_ERR, "fork: %m");
+                       exit (1);
+               case 0:
+                       break;
+               default:
+                       continue;
+               }
+
+               setproctitle("server");
+               nfssvc_flag = NFSSVC_NFSD;
+               nsd.nsd_nfsd = NULL;
+#ifdef NFSKERB
+               if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
+                   sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
+                   syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
+               nsd.nsd_authstr = (u_char *)&kt;
+               nsd.nsd_authlen = sizeof (kt);
+               nsd.nsd_verfstr = (u_char *)&kverf;
+               nsd.nsd_verflen = sizeof (kverf);
+#endif
+               while (nfssvc(nfssvc_flag, &nsd) < 0) {
+                       if (errno != ENEEDAUTH) {
+                               syslog(LOG_ERR, "nfssvc: %m");
+                               exit(1);
+                       }
+                       nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
+#ifdef NFSKERB
+                       /*
+                        * Get the Kerberos ticket out of the authenticator
+                        * verify it and convert the principal name to a user
+                        * name. The user name is then converted to a set of
+                        * user credentials via the password and group file.
+                        * Finally, decrypt the timestamp and validate it.
+                        * For more info see the IETF Draft "Authentication
+                        * in ONC RPC".
+                        */
+                       kt.length = ntohl(kt.length);
+                       if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
+                           kt.length > 0 && kt.length <=
+                           (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
+                           kin.w1 = NFS_KERBW1(kt);
+                           kt.mbz = 0;
+                           (void)strcpy(inst, "*");
+                           if (krb_rd_req(&kt, NFS_KERBSRV,
+                               inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
+                               krb_kntoln(&kauth, lnam) == KSUCCESS &&
+                               (pwd = getpwnam(lnam)) != NULL) {
+                               cr = &nsd.nsd_cr;
+                               cr->cr_uid = pwd->pw_uid;
+                               cr->cr_groups[0] = pwd->pw_gid;
+                               cr->cr_ngroups = 1;
+                               setgrent();
+                               while ((grp = getgrent()) != NULL) {
+                                       if (grp->gr_gid == cr->cr_groups[0])
+                                               continue;
+                                       for (cpp = grp->gr_mem;
+                                           *cpp != NULL; ++cpp)
+                                               if (!strcmp(*cpp, lnam))
+                                                       break;
+                                       if (*cpp == NULL)
+                                               continue;
+                                       cr->cr_groups[cr->cr_ngroups++]
+                                           = grp->gr_gid;
+                                       if (cr->cr_ngroups == NGROUPS)
+                                               break;
+                               }
+                               endgrent();
+
+                               /*
+                                * Get the timestamp verifier out of the
+                                * authenticator and verifier strings.
+                                */
+                               kin.t1 = kverf.t1;
+                               kin.t2 = kverf.t2;
+                               kin.w2 = kverf.w2;
+                               bzero((caddr_t)kivec, sizeof (kivec));
+                               bcopy((caddr_t)kauth.session,
+                                   (caddr_t)nsd.nsd_key,sizeof(kauth.session));
+
+                               /*
+                                * Decrypt the timestamp verifier in CBC mode.
+                                */
+                               XXX
+
+                               /*
+                                * Validate the timestamp verifier, to
+                                * check that the session key is ok.
+                                */
+                               nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
+                               nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
+                               nsd.nsd_ttl = ntohl(kout.w1);
+                               if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
+                                   nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
+                       }
+#endif /* NFSKERB */
+               }
+               exit(0);
+       }
+
+       /* If we are serving udp, set up the socket. */
+       if (udpflag) {
+               if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+                       syslog(LOG_ERR, "can't create udp socket");
+                       exit(1);
+               }
+               inetaddr.sin_family = AF_INET;
+               inetaddr.sin_addr.s_addr = INADDR_ANY;
+               inetaddr.sin_port = htons(NFS_PORT);
+               inetaddr.sin_len = sizeof(inetaddr);
+               if (bind(sock,
+                   (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
+                       syslog(LOG_ERR, "can't bind udp addr");
+                       exit(1);
+               }
+               if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
+                   !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
+                       syslog(LOG_ERR, "can't register with udp portmap");
+                       exit(1);
+               }
+               nfsdargs.sock = sock;
+               nfsdargs.name = NULL;
+               nfsdargs.namelen = 0;
+               if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
+                       syslog(LOG_ERR, "can't Add UDP socket");
+                       exit(1);
+               }
+               (void)close(sock);
+       }
+
+#ifdef ISO
+       /* If we are serving cltp, set up the socket. */
+       if (cltpflag) {
+               if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
+                       syslog(LOG_ERR, "can't create cltp socket");
+                       exit(1);
+               }
+               memset(&isoaddr, 0, sizeof(isoaddr));
+               isoaddr.siso_family = AF_ISO;
+               isoaddr.siso_tlen = 2;
+               cp = TSEL(&isoaddr);
+               *cp++ = (NFS_PORT >> 8);
+               *cp = (NFS_PORT & 0xff);
+               isoaddr.siso_len = sizeof(isoaddr);
+               if (bind(sock,
+                   (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
+                       syslog(LOG_ERR, "can't bind cltp addr");
+                       exit(1);
+               }
+#ifdef notyet
+               /*
+                * XXX
+                * Someday this should probably use "rpcbind", the son of
+                * portmap.
+                */
+               if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
+                       syslog(LOG_ERR, "can't register with udp portmap");
+                       exit(1);
+               }
+#endif /* notyet */
+               nfsdargs.sock = sock;
+               nfsdargs.name = NULL;
+               nfsdargs.namelen = 0;
+               if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
+                       syslog(LOG_ERR, "can't add UDP socket");
+                       exit(1);
+               }
+               close(sock);
+       }
+#endif /* ISO */
+
+       /* Now set up the master server socket waiting for tcp connections. */
+       on = 1;
+       FD_ZERO(&sockbits);
+       connect_type_cnt = 0;
+       if (tcpflag) {
+               if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+                       syslog(LOG_ERR, "can't create tcp socket");
+                       exit(1);
+               }
+               if (setsockopt(tcpsock,
+                   SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
+                       syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
+               inetaddr.sin_family = AF_INET;
+               inetaddr.sin_addr.s_addr = INADDR_ANY;
+               inetaddr.sin_port = htons(NFS_PORT);
+               inetaddr.sin_len = sizeof(inetaddr);
+               if (bind(tcpsock,
+                   (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
+                       syslog(LOG_ERR, "can't bind tcp addr");
+                       exit(1);
+               }
+               if (listen(tcpsock, 5) < 0) {
+                       syslog(LOG_ERR, "listen failed");
+                       exit(1);
+               }
+               if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
+                   !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
+                       syslog(LOG_ERR, "can't register tcp with portmap");
+                       exit(1);
+               }
+               FD_SET(tcpsock, &sockbits);
+               maxsock = tcpsock;
+               connect_type_cnt++;
+       }
+
+#ifdef notyet
+       /* Now set up the master server socket waiting for tp4 connections. */
+       if (tp4flag) {
+               if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
+                       syslog(LOG_ERR, "can't create tp4 socket");
+                       exit(1);
+               }
+               if (setsockopt(tp4sock,
+                   SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
+                       syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
+               memset(&isoaddr, 0, sizeof(isoaddr));
+               isoaddr.siso_family = AF_ISO;
+               isoaddr.siso_tlen = 2;
+               cp = TSEL(&isoaddr);
+               *cp++ = (NFS_PORT >> 8);
+               *cp = (NFS_PORT & 0xff);
+               isoaddr.siso_len = sizeof(isoaddr);
+               if (bind(tp4sock,
+                   (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
+                       syslog(LOG_ERR, "can't bind tp4 addr");
+                       exit(1);
+               }
+               if (listen(tp4sock, 5) < 0) {
+                       syslog(LOG_ERR, "listen failed");
+                       exit(1);
+               }
+               /*
+                * XXX
+                * Someday this should probably use "rpcbind", the son of
+                * portmap.
+                */
+               if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
+                       syslog(LOG_ERR, "can't register tcp with portmap");
+                       exit(1);
+               }
+               FD_SET(tp4sock, &sockbits);
+               maxsock = tp4sock;
+               connect_type_cnt++;
+       }
+
+       /* Now set up the master server socket waiting for tpip connections. */
+       if (tpipflag) {
+               if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
+                       syslog(LOG_ERR, "can't create tpip socket");
+                       exit(1);
+               }
+               if (setsockopt(tpipsock,
+                   SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
+                       syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
+               inetaddr.sin_family = AF_INET;
+               inetaddr.sin_addr.s_addr = INADDR_ANY;
+               inetaddr.sin_port = htons(NFS_PORT);
+               inetaddr.sin_len = sizeof(inetaddr);
+               if (bind(tpipsock,
+                   (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
+                       syslog(LOG_ERR, "can't bind tcp addr");
+                       exit(1);
+               }
+               if (listen(tpipsock, 5) < 0) {
+                       syslog(LOG_ERR, "listen failed");
+                       exit(1);
+               }
+               /*
+                * XXX
+                * Someday this should probably use "rpcbind", the son of
+                * portmap.
+                */
+               if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
+                       syslog(LOG_ERR, "can't register tcp with portmap");
+                       exit(1);
+               }
+               FD_SET(tpipsock, &sockbits);
+               maxsock = tpipsock;
+               connect_type_cnt++;
+       }
+#endif /* notyet */
+
+       if (connect_type_cnt == 0)
+               exit(0);
+
+       setproctitle("master");
+
+       /*
+        * Loop forever accepting connections and passing the sockets
+        * into the kernel for the mounts.
+        */
+       for (;;) {
+               ready = sockbits;
+               if (connect_type_cnt > 1) {
+                       if (select(maxsock + 1,
+                           &ready, NULL, NULL, NULL) < 1) {
+                               syslog(LOG_ERR, "select failed: %m");
+                               exit(1);
+                       }
+               }
+               if (tcpflag && FD_ISSET(tcpsock, &ready)) {
+                       len = sizeof(inetpeer);
+                       if ((msgsock = accept(tcpsock,
+                           (struct sockaddr *)&inetpeer, &len)) < 0) {
+                               syslog(LOG_ERR, "accept failed: %m");
+                               exit(1);
+                       }
+                       memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
+                       if (setsockopt(msgsock, SOL_SOCKET,
+                           SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
+                               syslog(LOG_ERR,
+                                   "setsockopt SO_KEEPALIVE: %m");
+                       nfsdargs.sock = msgsock;
+                       nfsdargs.name = (caddr_t)&inetpeer;
+                       nfsdargs.namelen = sizeof(inetpeer);
+                       nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
+                       (void)close(msgsock);
+               }
+#ifdef notyet
+               if (tp4flag && FD_ISSET(tp4sock, &ready)) {
+                       len = sizeof(isopeer);
+                       if ((msgsock = accept(tp4sock,
+                           (struct sockaddr *)&isopeer, &len)) < 0) {
+                               syslog(LOG_ERR, "accept failed: %m");
+                               exit(1);
+                       }
+                       if (setsockopt(msgsock, SOL_SOCKET,
+                           SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
+                               syslog(LOG_ERR,
+                                   "setsockopt SO_KEEPALIVE: %m");
+                       nfsdargs.sock = msgsock;
+                       nfsdargs.name = (caddr_t)&isopeer;
+                       nfsdargs.namelen = len;
+                       nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
+                       (void)close(msgsock);
+               }
+               if (tpipflag && FD_ISSET(tpipsock, &ready)) {
+                       len = sizeof(inetpeer);
+                       if ((msgsock = accept(tpipsock,
+                           (struct sockaddr *)&inetpeer, &len)) < 0) {
+                               syslog(LOG_ERR, "Accept failed: %m");
+                               exit(1);
+                       }
+                       if (setsockopt(msgsock, SOL_SOCKET,
+                           SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
+                               syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
+                       nfsdargs.sock = msgsock;
+                       nfsdargs.name = (caddr_t)&inetpeer;
+                       nfsdargs.namelen = len;
+                       nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
+                       (void)close(msgsock);
+               }
+#endif /* notyet */
+       }
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
+       exit(1);
+}
+
+void
+nonfs(signo)
+       int signo;
+{
+       syslog(LOG_ERR, "missing system call: NFS not available.");
+}
+
+void
+reapchild(signo)
+       int signo;
+{
+
+       while (wait3(NULL, WNOHANG, NULL) > 0);
+}
+
+void
+setproctitle(a)
+       char *a;
+{
+       register char *cp;
+       char buf[80];
+
+       cp = Argv[0];
+       (void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
+       (void)strncpy(cp, buf, LastArg - cp);
+       cp += strlen(cp);
+       while (cp < LastArg)
+               *cp++ = '\0';
+}
diff --git a/nfsiod.tproj/Makefile b/nfsiod.tproj/Makefile
new file mode 100644 (file)
index 0000000..fa0ae2f
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = nfsiod
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = nfsiod.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist nfsiod.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DNFS -DMACH_USER_API
+WINDOWS_PB_CFLAGS = -DNFS -DMACH_USER_API
+PDO_UNIX_PB_CFLAGS = -DNFS -DMACH_USER_API
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/nfsiod.tproj/Makefile.dist b/nfsiod.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..72db42b
--- /dev/null
@@ -0,0 +1,7 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  nfsiod
+CFLAGS+=-DNFS
+MAN8=  nfsiod.0
+
+.include <bsd.prog.mk>
diff --git a/nfsiod.tproj/Makefile.preamble b/nfsiod.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/nfsiod.tproj/PB.project b/nfsiod.tproj/PB.project
new file mode 100644 (file)
index 0000000..8d6f93f
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (nfsiod.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, nfsiod.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = nfsiod; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = nfsiod; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = nfsiod; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = nfsiod; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/nfsiod.tproj/nfsiod.8 b/nfsiod.tproj/nfsiod.8
new file mode 100644 (file)
index 0000000..2acd365
--- /dev/null
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)nfsiod.8   8.2 (Berkeley) 2/22/94
+.\"
+.Dd February 22, 1994
+.Dt NFSIOD 8
+.Os
+.Sh NAME
+.Nm nfsiod
+.Nd local
+.Tn NFS
+asynchronous I/O server
+.Sh SYNOPSIS
+.Nm nfsiod
+.Op Fl n Ar num_servers
+.Sh DESCRIPTION
+.Nm Nfsiod
+runs on an
+.Tn NFS
+client machine to service asynchronous I/O requests to its server.
+It improves performance but is not required for correct operation.
+.Pp
+Unless otherwise specified, a single server is started.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl n
+Specify how many servers are to be started.
+.El
+.Pp
+A client should run enough daemons to handle its maximum
+level of concurrency, typically four to six.
+.Pp
+The
+.Nm nfsiod
+utility exits 0 on success, and >0 if an error occurs.
+.Sh SEE ALSO
+.Xr nfsstat 1 ,
+.Xr nfssvc 2 ,
+.Xr mountd 8 ,
+.Xr portmap 8
+.Sh HISTORY
+The
+.Nm nfsiod
+utility first appeared in 4.4BSD.
diff --git a/nfsiod.tproj/nfsiod.c b/nfsiod.tproj/nfsiod.c
new file mode 100644 (file)
index 0000000..07a87ff
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/ucred.h>
+#include <sys/wait.h>
+
+#include <sys/mount.h>
+#include <sys/time.h>
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Global defs */
+#ifdef DEBUG
+int debug = 1;
+#else
+int debug = 0;
+#endif
+
+void nonfs __P((int));
+void reapchild __P((int));
+void usage __P((void));
+
+/*
+ * Nfsiod does asynchronous buffered I/O on behalf of the NFS client.
+ * It does not have to be running for correct operation, but will
+ * improve throughput.
+ */
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int ch, num_servers;
+
+#define        MAXNFSDCNT      20
+#define        DEFNFSDCNT       1
+       num_servers = DEFNFSDCNT;
+       while ((ch = getopt(argc, argv, "n:")) != EOF)
+               switch (ch) {
+               case 'n':
+                       num_servers = atoi(optarg);
+                       if (num_servers < 1 || num_servers > MAXNFSDCNT) {
+                               warnx("nfsiod count %d; reset to %d",
+                                   DEFNFSDCNT);
+                               num_servers = DEFNFSDCNT;
+                       }
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       /*
+        * XXX
+        * Backward compatibility, trailing number is the count of daemons.
+        */
+       if (argc > 1)
+               usage();
+       if (argc == 1) {
+               num_servers = atoi(argv[0]);
+               if (num_servers < 1 || num_servers > MAXNFSDCNT) {
+                       warnx("nfsiod count %d; reset to %d", DEFNFSDCNT);
+                       num_servers = DEFNFSDCNT;
+               }
+       }
+
+       if (debug == 0) {
+               daemon(0, 0);
+               (void)signal(SIGHUP, SIG_IGN);
+               (void)signal(SIGINT, SIG_IGN);
+               (void)signal(SIGQUIT, SIG_IGN);
+               (void)signal(SIGSYS, nonfs);
+       }
+       (void)signal(SIGCHLD, reapchild);
+
+       openlog("nfsiod:", LOG_PID, LOG_DAEMON);
+
+       while (num_servers--)
+               switch (fork()) {
+               case -1:
+                       syslog(LOG_ERR, "fork: %m");
+                       exit (1);
+               case 0:
+                       if (nfssvc(NFSSVC_BIOD, NULL) < 0) {
+                               syslog(LOG_ERR, "nfssvc: %m");
+                               exit (1);
+                       }
+                       exit(0);
+               }
+       exit (0);
+}
+
+void
+nonfs(signo)
+       int signo;
+{
+       syslog(LOG_ERR, "missing system call: NFS not available.");
+}
+
+void
+reapchild(signo)
+       int signo;
+{
+
+       while (wait3(NULL, WNOHANG, NULL));
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr, "usage: nfsiod [-n num_servers]\n");
+       exit(1);
+}
diff --git a/nfsstat.tproj/Makefile b/nfsstat.tproj/Makefile
new file mode 100644 (file)
index 0000000..d20d30c
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = nfsstat
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = nfsstat.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble nfsstat.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DNFS -DMACH_USER_API
+WINDOWS_PB_CFLAGS = -DNFS -DMACH_USER_API
+PDO_UNIX_PB_CFLAGS = -DNFS -DMACH_USER_API
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/nfsstat.tproj/Makefile.postamble b/nfsstat.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..b5bfe61
--- /dev/null
@@ -0,0 +1,2 @@
+INSTALL_AS_GROUP =     kmem
+INSTALL_PERMISSIONS =2555
diff --git a/nfsstat.tproj/Makefile.preamble b/nfsstat.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..925a5c7
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/nfsstat.tproj/PB.project b/nfsstat.tproj/PB.project
new file mode 100644 (file)
index 0000000..d4ad122
--- /dev/null
@@ -0,0 +1,31 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (nfsstat.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, nfsstat.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDTOOL = make; 
+    NEXTSTEP_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = nfsstat; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = make; 
+    WINDOWS_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/nfsstat.tproj/nfsstat.1 b/nfsstat.tproj/nfsstat.1
new file mode 100644 (file)
index 0000000..3acda6c
--- /dev/null
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)nfsstat.1  8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt NFSSTAT 1
+.Os BSD 4.4
+.Sh NAME
+.Nm nfsstat
+.Nd display
+.Tn NFS
+statistics
+.Sh SYNOPSIS
+.Nm nfsstat
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar wait
+.Sh DESCRIPTION
+.Nm Nfsstat
+displays statistics kept about
+.Tn NFS
+client and server activity.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl N
+Extract the name list from the specified system instead of the default
+.Pa /vmunix .
+.It Fl w
+Display a shorter summary of
+.Tn NFS
+activity for both the client and server at
+.Ar wait
+second intervals.
+.El
+.Sh FILES
+.Bl -tag -width /dev/kmem -compact
+.It Pa /vmunix
+default kernel namelist
+.It Pa /dev/kmem
+default memory file
+.El
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr netstat 1 ,
+.Xr ps 1 ,
+.Xr systat 1 ,
+.Xr vmstat 1 ,
+.Xr iostat 8 ,
+.Xr pstat 8 ,
+.Sh HISTORY
+The
+.Nm nfsstat
+command appears in
+.Bx 4.4 .
diff --git a/nfsstat.tproj/nfsstat.c b/nfsstat.tproj/nfsstat.c
new file mode 100644 (file)
index 0000000..7bd1ce2
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* 
+ * Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved
+ *
+ * Copyright (c) 1983, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *     @(#)nfsstat.c   8.2 (Berkeley) 3/31/95
+ */
+
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <kvm.h>
+#include <nlist.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <err.h>
+
+#define SHOW_SERVER 0x01
+#define SHOW_CLIENT 0x02
+#define SHOW_ALL (SHOW_SERVER | SHOW_CLIENT)
+
+struct nlist nl[] = {
+#define        N_NFSSTAT       0
+       { "_nfsstats" },
+       {""},
+};
+kvm_t *kd;
+
+static int deadkernel = 0;
+
+void intpr __P((u_long, u_int));
+void printhdr __P((void));
+void sidewaysintpr __P((u_int, u_long, u_int));
+void usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern int optind;
+       extern char *optarg;
+       u_int interval;
+       u_int display = SHOW_ALL;
+       int ch;
+       char *memf, *nlistf;
+       char errbuf[80];
+
+       interval = 0;
+       memf = nlistf = NULL;
+       while ((ch = getopt(argc, argv, "M:N:w:sc")) != EOF)
+               switch(ch) {
+               case 'M':
+                       memf = optarg;
+                       break;
+               case 'N':
+                       nlistf = optarg;
+                       break;
+               case 'w':
+                       interval = atoi(optarg);
+                       break;
+               case 's':
+                       display = SHOW_SERVER;
+                       break;
+               case 'c':
+                       display = SHOW_CLIENT;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+#define        BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+       if (*argv) {
+               interval = atoi(*argv);
+               if (*++argv) {
+                       nlistf = *argv;
+                       if (*++argv)
+                               memf = *argv;
+               }
+       }
+#endif
+       /*
+        * Discard setgid privileges if not the running kernel so that bad
+        * guys can't print interesting stuff from kernel memory.
+        */
+       if (nlistf != NULL || memf != NULL) {
+               setegid(getgid());
+               setgid(getgid());
+               deadkernel = 1;
+
+               if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
+                                       errbuf)) == 0) {
+                       errx(1, "kvm_openfiles: %s", errbuf);
+               }
+               if (kvm_nlist(kd, nl) != 0) {
+                       errx(1, "kvm_nlist: can't get names");
+               }
+       }
+
+       if (interval)
+               sidewaysintpr(interval, nl[N_NFSSTAT].n_value, display);
+       else
+               intpr(nl[N_NFSSTAT].n_value, display);
+       exit(0);
+}
+
+/*
+ * Read the nfs stats using sysctl(3) for live kernels, or kvm_read
+ * for dead ones.
+ */
+void
+readstats(stp)
+       struct nfsstats *stp;
+{
+       if(deadkernel) {
+               if(kvm_read(kd, (u_long)nl[N_NFSSTAT].n_value, stp,
+                           sizeof *stp) < 0) {
+                       err(1, "kvm_read");
+               }
+       } else {
+               int name[3];
+               size_t buflen = sizeof *stp;
+               struct vfsconf vfc;
+               extern int getvfsbyname(char *, struct vfsconf *);
+
+               if (getvfsbyname("nfs", &vfc) < 0)
+                       err(1, "getvfsbyname: NFS not compiled into kernel");
+               name[0] = CTL_VFS;
+               name[1] = vfc.vfc_typenum;
+               name[2] = NFS_NFSSTATS;
+               if (sysctl(name, 3, stp, &buflen, (void *)0, (size_t)0) < 0) {
+                       err(1, "sysctl");
+               }
+       }
+}
+
+/*
+ * Print a description of the nfs stats.
+ */
+void
+intpr(nfsstataddr, display)
+       u_long nfsstataddr;
+       u_int display;
+{
+       struct nfsstats nfsstats;
+
+       readstats(&nfsstats);
+
+       if (display & SHOW_CLIENT) {
+               printf("Client Info:\n");
+               printf("Rpc Counts:\n");
+               printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+                      "Getattr", "Setattr", "Lookup", "Readlink", "Read",
+                      "Write", "Create", "Remove");
+               printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
+                      nfsstats.rpccnt[NFSPROC_GETATTR],
+                      nfsstats.rpccnt[NFSPROC_SETATTR],
+                      nfsstats.rpccnt[NFSPROC_LOOKUP],
+                      nfsstats.rpccnt[NFSPROC_READLINK],
+                      nfsstats.rpccnt[NFSPROC_READ],
+                      nfsstats.rpccnt[NFSPROC_WRITE],
+                      nfsstats.rpccnt[NFSPROC_CREATE],
+                      nfsstats.rpccnt[NFSPROC_REMOVE]);
+               printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+                      "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
+                      "Readdir", "RdirPlus", "Access");
+               printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
+                      nfsstats.rpccnt[NFSPROC_RENAME],
+                      nfsstats.rpccnt[NFSPROC_LINK],
+                      nfsstats.rpccnt[NFSPROC_SYMLINK],
+                      nfsstats.rpccnt[NFSPROC_MKDIR],
+                      nfsstats.rpccnt[NFSPROC_RMDIR],
+                      nfsstats.rpccnt[NFSPROC_READDIR],
+                      nfsstats.rpccnt[NFSPROC_READDIRPLUS],
+                      nfsstats.rpccnt[NFSPROC_ACCESS]);
+               printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+                      "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit",
+                      "GLease", "Vacate", "Evict");
+               printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
+                      nfsstats.rpccnt[NFSPROC_MKNOD],
+                      nfsstats.rpccnt[NFSPROC_FSSTAT],
+                      nfsstats.rpccnt[NFSPROC_FSINFO],
+                      nfsstats.rpccnt[NFSPROC_PATHCONF],
+                      nfsstats.rpccnt[NFSPROC_COMMIT],
+                      nfsstats.rpccnt[NQNFSPROC_GETLEASE],
+                      nfsstats.rpccnt[NQNFSPROC_VACATED],
+                      nfsstats.rpccnt[NQNFSPROC_EVICTED]);
+               printf("Rpc Info:\n");
+               printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
+                      "TimedOut", "Invalid", "X Replies", "Retries", "Requests");
+               printf("%9d %9d %9d %9d %9d\n",
+                      nfsstats.rpctimeouts,
+                      nfsstats.rpcinvalid,
+                      nfsstats.rpcunexpected,
+                      nfsstats.rpcretries,
+                      nfsstats.rpcrequests);
+               printf("Cache Info:\n");
+               printf("%9.9s %9.9s %9.9s %9.9s",
+                      "Attr Hits", "Misses", "Lkup Hits", "Misses");
+               printf(" %9.9s %9.9s %9.9s %9.9s\n",
+                      "BioR Hits", "Misses", "BioW Hits", "Misses");
+               printf("%9d %9d %9d %9d",
+                      nfsstats.attrcache_hits, nfsstats.attrcache_misses,
+                      nfsstats.lookupcache_hits, nfsstats.lookupcache_misses);
+               printf(" %9d %9d %9d %9d\n",
+                      nfsstats.biocache_reads-nfsstats.read_bios,
+                      nfsstats.read_bios,
+                      nfsstats.biocache_writes-nfsstats.write_bios,
+                      nfsstats.write_bios);
+               printf("%9.9s %9.9s %9.9s %9.9s",
+                      "BioRLHits", "Misses", "BioD Hits", "Misses");
+               printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
+               printf("%9d %9d %9d %9d",
+                      nfsstats.biocache_readlinks-nfsstats.readlink_bios,
+                      nfsstats.readlink_bios,
+                      nfsstats.biocache_readdirs-nfsstats.readdir_bios,
+                      nfsstats.readdir_bios);
+               printf(" %9d %9d\n",
+                      nfsstats.direofcache_hits, nfsstats.direofcache_misses);
+        }
+       if (display & SHOW_SERVER) {
+               printf("\nServer Info:\n");
+               printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+                      "Getattr", "Setattr", "Lookup", "Readlink", "Read",
+                      "Write", "Create", "Remove");
+               printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
+                      nfsstats.srvrpccnt[NFSPROC_GETATTR],
+                      nfsstats.srvrpccnt[NFSPROC_SETATTR],
+                      nfsstats.srvrpccnt[NFSPROC_LOOKUP],
+                      nfsstats.srvrpccnt[NFSPROC_READLINK],
+                      nfsstats.srvrpccnt[NFSPROC_READ],
+                      nfsstats.srvrpccnt[NFSPROC_WRITE],
+                      nfsstats.srvrpccnt[NFSPROC_CREATE],
+                      nfsstats.srvrpccnt[NFSPROC_REMOVE]);
+               printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+                      "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
+                      "Readdir", "RdirPlus", "Access");
+               printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
+                      nfsstats.srvrpccnt[NFSPROC_RENAME],
+                      nfsstats.srvrpccnt[NFSPROC_LINK],
+                      nfsstats.srvrpccnt[NFSPROC_SYMLINK],
+                      nfsstats.srvrpccnt[NFSPROC_MKDIR],
+                      nfsstats.srvrpccnt[NFSPROC_RMDIR],
+                      nfsstats.srvrpccnt[NFSPROC_READDIR],
+                      nfsstats.srvrpccnt[NFSPROC_READDIRPLUS],
+                      nfsstats.srvrpccnt[NFSPROC_ACCESS]);
+               printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+                      "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit",
+                      "GLease", "Vacate", "Evict");
+               printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
+                      nfsstats.srvrpccnt[NFSPROC_MKNOD],
+                      nfsstats.srvrpccnt[NFSPROC_FSSTAT],
+                      nfsstats.srvrpccnt[NFSPROC_FSINFO],
+                      nfsstats.srvrpccnt[NFSPROC_PATHCONF],
+                      nfsstats.srvrpccnt[NFSPROC_COMMIT],
+                      nfsstats.srvrpccnt[NQNFSPROC_GETLEASE],
+                      nfsstats.srvrpccnt[NQNFSPROC_VACATED],
+                      nfsstats.srvrpccnt[NQNFSPROC_EVICTED]);
+               printf("Server Ret-Failed\n");
+               printf("%17d\n", nfsstats.srvrpc_errs);
+               printf("Server Faults\n");
+               printf("%13d\n", nfsstats.srv_errs);
+               printf("Server Cache Stats:\n");
+               printf("%9.9s %9.9s %9.9s %9.9s\n",
+                      "Inprog", "Idem", "Non-idem", "Misses");
+               printf("%9d %9d %9d %9d\n",
+                      nfsstats.srvcache_inproghits,
+                      nfsstats.srvcache_idemdonehits,
+                      nfsstats.srvcache_nonidemdonehits,
+                      nfsstats.srvcache_misses);
+               printf("Server Lease Stats:\n");
+               printf("%9.9s %9.9s %9.9s\n",
+                      "Leases", "PeakL", "GLeases");
+               printf("%9d %9d %9d\n",
+                      nfsstats.srvnqnfs_leases,
+                      nfsstats.srvnqnfs_maxleases,
+                      nfsstats.srvnqnfs_getleases);
+               printf("Server Write Gathering:\n");
+               printf("%9.9s %9.9s %9.9s\n",
+                      "WriteOps", "WriteRPC", "Opsaved");
+               printf("%9d %9d %9d\n",
+                      nfsstats.srvvop_writes,
+                      nfsstats.srvrpccnt[NFSPROC_WRITE],
+                      nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes);
+       }
+}
+
+u_char signalled;                      /* set if alarm goes off "early" */
+
+/*
+ * Print a running summary of nfs statistics.
+ * Repeat display every interval seconds, showing statistics
+ * collected over that interval.  Assumes that interval is non-zero.
+ * First line printed at top of screen is always cumulative.
+ */
+void
+sidewaysintpr(interval, off, display)
+       u_int interval;
+       u_long off;
+       u_int display;
+{
+       struct nfsstats nfsstats, lastst;
+       int hdrcnt, oldmask;
+       void catchalarm();
+
+       (void)signal(SIGALRM, catchalarm);
+       signalled = 0;
+       (void)alarm(interval);
+       bzero((caddr_t)&lastst, sizeof(lastst));
+
+       for (hdrcnt = 1;;) {
+               if (!--hdrcnt) {
+                       printhdr();
+                       hdrcnt = 20;
+               }
+               readstats(&nfsstats);
+               if (display & SHOW_CLIENT)
+                 printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n",
+                   nfsstats.rpccnt[NFSPROC_GETATTR]-lastst.rpccnt[NFSPROC_GETATTR],
+                   nfsstats.rpccnt[NFSPROC_LOOKUP]-lastst.rpccnt[NFSPROC_LOOKUP],
+                   nfsstats.rpccnt[NFSPROC_READLINK]-lastst.rpccnt[NFSPROC_READLINK],
+                   nfsstats.rpccnt[NFSPROC_READ]-lastst.rpccnt[NFSPROC_READ],
+                   nfsstats.rpccnt[NFSPROC_WRITE]-lastst.rpccnt[NFSPROC_WRITE],
+                   nfsstats.rpccnt[NFSPROC_RENAME]-lastst.rpccnt[NFSPROC_RENAME],
+                   nfsstats.rpccnt[NFSPROC_ACCESS]-lastst.rpccnt[NFSPROC_ACCESS],
+                   (nfsstats.rpccnt[NFSPROC_READDIR]-lastst.rpccnt[NFSPROC_READDIR])
+                   +(nfsstats.rpccnt[NFSPROC_READDIRPLUS]-lastst.rpccnt[NFSPROC_READDIRPLUS]));
+               if (display & SHOW_SERVER)
+                 printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n",
+                   nfsstats.srvrpccnt[NFSPROC_GETATTR]-lastst.srvrpccnt[NFSPROC_GETATTR],
+                   nfsstats.srvrpccnt[NFSPROC_LOOKUP]-lastst.srvrpccnt[NFSPROC_LOOKUP],
+                   nfsstats.srvrpccnt[NFSPROC_READLINK]-lastst.srvrpccnt[NFSPROC_READLINK],
+                   nfsstats.srvrpccnt[NFSPROC_READ]-lastst.srvrpccnt[NFSPROC_READ],
+                   nfsstats.srvrpccnt[NFSPROC_WRITE]-lastst.srvrpccnt[NFSPROC_WRITE],
+                   nfsstats.srvrpccnt[NFSPROC_RENAME]-lastst.srvrpccnt[NFSPROC_RENAME],
+                   nfsstats.srvrpccnt[NFSPROC_ACCESS]-lastst.srvrpccnt[NFSPROC_ACCESS],
+                   (nfsstats.srvrpccnt[NFSPROC_READDIR]-lastst.srvrpccnt[NFSPROC_READDIR])
+                   +(nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]-lastst.srvrpccnt[NFSPROC_READDIRPLUS]));
+               lastst = nfsstats;
+               fflush(stdout);
+               oldmask = sigblock(sigmask(SIGALRM));
+               if (!signalled)
+                       sigpause(0);
+               sigsetmask(oldmask);
+               signalled = 0;
+               (void)alarm(interval);
+       }
+       /*NOTREACHED*/
+}
+
+void
+printhdr()
+{
+       printf("        %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
+           "Getattr", "Lookup", "Readlink", "Read", "Write", "Rename",
+           "Access", "Readdir");
+       fflush(stdout);
+}
+
+/*
+ * Called if an interval expires before sidewaysintpr has completed a loop.
+ * Sets a flag to not wait for the alarm.
+ */
+void
+catchalarm()
+{
+       signalled = 1;
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr,
+           "usage: nfsstat [-cs] [-M core] [-N system] [-w interval]\n");
+       exit(1);
+}
diff --git a/pcap/Makefile b/pcap/Makefile
new file mode 100644 (file)
index 0000000..9f3d6f9
--- /dev/null
@@ -0,0 +1,63 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = pcap
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Library
+
+HFILES = ethertype.h gencode.h pcap-int.h pcap-namedb.h pcap.h
+
+OTHERLINKED = grammar.y scanner.l
+
+CFILES = bpf_filter.c bpf_image.c etherent.c gencode.c inet.c\
+         nametoaddr.c optimize.c pcap-bpf.c pcap.c savefile.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+OTHERLINKEDOFILES = grammar.o scanner.o
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CURRENTLY_ACTIVE_VERSION = YES
+DEPLOY_WITH_VERSION_NAME = A
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = library.make
+NEXTSTEP_INSTALLDIR = /usr/lib
+WINDOWS_INSTALLDIR = LOCAL_DEVELOPER_DIR/Libraries
+PDO_UNIX_INSTALLDIR = /usr/lib
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -traditional-cpp
+PROJECT_HEADERS = pcap.h pcap-namedb.h
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+WINDOWS_PUBLIC_HEADERS_DIR = LOCAL_DEVELOPER_DIR/Headers/$(NAME)
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/pcap/Makefile.postamble b/pcap/Makefile.postamble
new file mode 100644 (file)
index 0000000..36381d4
--- /dev/null
@@ -0,0 +1,122 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/pcap/Makefile.preamble b/pcap/Makefile.preamble
new file mode 100644 (file)
index 0000000..0e03ce1
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS += -seg1addr 0x59400000
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/pcap/PB.project b/pcap/PB.project
new file mode 100644 (file)
index 0000000..cb13890
--- /dev/null
@@ -0,0 +1,48 @@
+{
+    CURRENTLY_ACTIVE_VERSION = YES; 
+    DEPLOY_WITH_VERSION_NAME = A; 
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        CLASSES = (); 
+        FRAMEWORKS = (); 
+        H_FILES = (ethertype.h, gencode.h, "pcap-int.h", "pcap-namedb.h", pcap.h); 
+        OTHER_LINKED = (
+            bpf_filter.c, 
+            bpf_image.c, 
+            etherent.c, 
+            gencode.c, 
+            grammar.y, 
+            inet.c, 
+            nametoaddr.c, 
+            optimize.c, 
+            "pcap-bpf.c", 
+            pcap.c, 
+            savefile.c, 
+            scanner.l
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        PROJECT_HEADERS = (pcap.h, "pcap-namedb.h"); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-traditional-cpp"; 
+    NEXTSTEP_INSTALLDIR = /usr/lib; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = /bin/gnumake; 
+    PDO_UNIX_INSTALLDIR = /usr/lib; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = pcap; 
+    PROJECTTYPE = Library; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = LOCAL_DEVELOPER_DIR/Libraries; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+    WINDOWS_PUBLICHEADERSDIR = "LOCAL_DEVELOPER_DIR/Headers/$(NAME)"; 
+}
diff --git a/pcap/bpf_filter.c b/pcap/bpf_filter.c
new file mode 100644 (file)
index 0000000..dca0d0a
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#if defined(sparc) || defined(hppa)
+#define BPF_ALIGN
+#endif
+
+#ifndef BPF_ALIGN
+#define EXTRACT_SHORT(p)       ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p)                (ntohl(*(u_int32_t *)p))
+#else
+#define EXTRACT_SHORT(p)\
+       ((u_short)\
+               ((u_short)*((u_char *)p+0)<<8|\
+                (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+               ((u_int32_t)*((u_char *)p+0)<<24|\
+                (u_int32_t)*((u_char *)p+1)<<16|\
+                (u_int32_t)*((u_char *)p+2)<<8|\
+                (u_int32_t)*((u_char *)p+3)<<0)
+#endif
+
+#ifdef KERNEL
+#include <sys/mbuf.h>
+#define MINDEX(m, k) \
+{ \
+       register int len = m->m_len; \
+ \
+       while (k >= len) { \
+               k -= len; \
+               m = m->m_next; \
+               if (m == 0) \
+                       return 0; \
+               len = m->m_len; \
+       } \
+}
+
+static int
+m_xword(m, k, err)
+       register struct mbuf *m;
+       register int k, *err;
+{
+       register int len;
+       register u_char *cp, *np;
+       register struct mbuf *m0;
+
+       len = m->m_len;
+       while (k >= len) {
+               k -= len;
+               m = m->m_next;
+               if (m == 0)
+                       goto bad;
+               len = m->m_len;
+       }
+       cp = mtod(m, u_char *) + k;
+       if (len - k >= 4) {
+               *err = 0;
+               return EXTRACT_LONG(cp);
+       }
+       m0 = m->m_next;
+       if (m0 == 0 || m0->m_len + len - k < 4)
+               goto bad;
+       *err = 0;
+       np = mtod(m0, u_char *);
+       switch (len - k) {
+
+       case 1:
+               return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
+
+       case 2:
+               return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) | 
+                       np[1];
+
+       default:
+               return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) |
+                       np[0];
+       }
+    bad:
+       *err = 1;
+       return 0;
+}
+
+static int
+m_xhalf(m, k, err)
+       register struct mbuf *m;
+       register int k, *err;
+{
+       register int len;
+       register u_char *cp;
+       register struct mbuf *m0;
+
+       len = m->m_len;
+       while (k >= len) {
+               k -= len;
+               m = m->m_next;
+               if (m == 0)
+                       goto bad;
+               len = m->m_len;
+       }
+       cp = mtod(m, u_char *) + k;
+       if (len - k >= 2) {
+               *err = 0;
+               return EXTRACT_SHORT(cp);
+       }
+       m0 = m->m_next;
+       if (m0 == 0)
+               goto bad;
+       *err = 0;
+       return (cp[k] << 8) | mtod(m0, u_char *)[0];
+ bad:
+       *err = 1;
+       return 0;
+}
+#endif
+
+#include <net/bpf.h>
+
+/*
+ * Execute the filter program starting at pc on the packet p
+ * wirelen is the length of the original packet
+ * buflen is the amount of data present
+ */
+u_int
+bpf_filter(pc, p, wirelen, buflen)
+       register struct bpf_insn *pc;
+       register u_char *p;
+       u_int wirelen;
+       register u_int buflen;
+{
+       register u_int32_t A, X;
+       register int k;
+       int32_t mem[BPF_MEMWORDS];
+
+       if (pc == 0)
+               /*
+                * No filter means accept all.
+                */
+               return (u_int)-1;
+#ifdef lint
+       A = 0;
+       X = 0;
+#endif
+       --pc;
+       while (1) {
+               ++pc;
+               switch (pc->code) {
+
+               default:
+#ifdef KERNEL
+                       return 0;
+#else
+                       abort();
+#endif                 
+               case BPF_RET|BPF_K:
+                       return (u_int)pc->k;
+
+               case BPF_RET|BPF_A:
+                       return (u_int)A;
+
+               case BPF_LD|BPF_W|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(int32_t) > buflen) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xword((struct mbuf *)p, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+#ifdef BPF_ALIGN
+                       if (((int)(p + k) & 3) != 0)
+                               A = EXTRACT_LONG(&p[k]);
+                       else
+#endif
+                               A = ntohl(*(long *)(p + k));
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(short) > buflen) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xhalf((struct mbuf *)p, k, &merr);
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_ABS:
+                       k = pc->k;
+                       if (k >= buflen) {
+#ifdef KERNEL
+                               register struct mbuf *m;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (struct mbuf *)p;
+                               MINDEX(m, k);
+                               A = mtod(m, u_char *)[k];
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_LEN:
+                       A = wirelen;
+                       continue;
+
+               case BPF_LDX|BPF_W|BPF_LEN:
+                       X = wirelen;
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(int32_t) > buflen) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xword((struct mbuf *)p, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+#ifdef BPF_ALIGN
+                       if (((int)(p + k) & 3) != 0)
+                               A = EXTRACT_LONG(&p[k]);
+                       else
+#endif
+                               A = ntohl(*(long *)(p + k));
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(short) > buflen) {
+#ifdef KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xhalf((struct mbuf *)p, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_IND:
+                       k = X + pc->k;
+                       if (k >= buflen) {
+#ifdef KERNEL
+                               register struct mbuf *m;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (struct mbuf *)p;
+                               MINDEX(m, k);
+                               A = mtod(m, char *)[k];
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LDX|BPF_MSH|BPF_B:
+                       k = pc->k;
+                       if (k >= buflen) {
+#ifdef KERNEL
+                               register struct mbuf *m;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (struct mbuf *)p;
+                               MINDEX(m, k);
+                               X = (mtod(m, char *)[k] & 0xf) << 2;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       X = (p[pc->k] & 0xf) << 2;
+                       continue;
+
+               case BPF_LD|BPF_IMM:
+                       A = pc->k;
+                       continue;
+
+               case BPF_LDX|BPF_IMM:
+                       X = pc->k;
+                       continue;
+
+               case BPF_LD|BPF_MEM:
+                       A = mem[pc->k];
+                       continue;
+                       
+               case BPF_LDX|BPF_MEM:
+                       X = mem[pc->k];
+                       continue;
+
+               case BPF_ST:
+                       mem[pc->k] = A;
+                       continue;
+
+               case BPF_STX:
+                       mem[pc->k] = X;
+                       continue;
+
+               case BPF_JMP|BPF_JA:
+                       pc += pc->k;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_K:
+                       pc += (A > pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_K:
+                       pc += (A >= pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_K:
+                       pc += (A == pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_K:
+                       pc += (A & pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_X:
+                       pc += (A > X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_X:
+                       pc += (A >= X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_X:
+                       pc += (A == X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_X:
+                       pc += (A & X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_X:
+                       A += X;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_X:
+                       A -= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_X:
+                       A *= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_X:
+                       if (X == 0)
+                               return 0;
+                       A /= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_X:
+                       A &= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_X:
+                       A |= X;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_X:
+                       A <<= X;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_X:
+                       A >>= X;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_K:
+                       A += pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_K:
+                       A -= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_K:
+                       A *= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_K:
+                       A /= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_K:
+                       A &= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_K:
+                       A |= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_K:
+                       A <<= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_K:
+                       A >>= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_NEG:
+                       A = -A;
+                       continue;
+
+               case BPF_MISC|BPF_TAX:
+                       X = A;
+                       continue;
+
+               case BPF_MISC|BPF_TXA:
+                       A = X;
+                       continue;
+               }
+       }
+}
+
+#ifdef KERNEL
+/*
+ * Return true if the 'fcode' is a valid filter program.
+ * The constraints are that each jump be forward and to a valid
+ * code.  The code must terminate with either an accept or reject. 
+ * 'valid' is an array for use by the routine (it must be at least
+ * 'len' bytes long).  
+ *
+ * The kernel needs to be able to verify an application's filter code.
+ * Otherwise, a bogus program could easily crash the system.
+ */
+int
+bpf_validate(f, len)
+       struct bpf_insn *f;
+       int len;
+{
+       register int i;
+       register struct bpf_insn *p;
+
+       for (i = 0; i < len; ++i) {
+               /*
+                * Check that that jumps are forward, and within 
+                * the code block.
+                */
+               p = &f[i];
+               if (BPF_CLASS(p->code) == BPF_JMP) {
+                       register int from = i + 1;
+
+                       if (BPF_OP(p->code) == BPF_JA) {
+                               if (from + p->k >= len)
+                                       return 0;
+                       }
+                       else if (from + p->jt >= len || from + p->jf >= len)
+                               return 0;
+               }
+               /*
+                * Check that memory operations use valid addresses.
+                */
+               if ((BPF_CLASS(p->code) == BPF_ST ||
+                    (BPF_CLASS(p->code) == BPF_LD && 
+                     (p->code & 0xe0) == BPF_MEM)) &&
+                   (p->k >= BPF_MEMWORDS || p->k < 0))
+                       return 0;
+               /*
+                * Check for constant division by 0.
+                */
+               if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
+                       return 0;
+       }
+       return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
+#endif
diff --git a/pcap/bpf_image.c b/pcap/bpf_image.c
new file mode 100644 (file)
index 0000000..f5177d9
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*      $OpenBSD */
+
+/*
+ * Copyright (c) 1990, 1991, 1992, 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+       "@(#) Header: bpf_image.c,v 1.19 95/11/26 14:02:36 leres Exp (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <net/bpf.h>
+
+#include <pcap.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+char *
+bpf_image(p, n)
+       struct bpf_insn *p;
+       int n;
+{
+       int v;
+       char *fmt, *op;
+       static char image[256];
+       char operand[64];
+
+       v = p->k;
+       switch (p->code) {
+
+       default:
+               op = "unimp";
+               fmt = "0x%x";
+               v = p->code;
+               break;
+
+       case BPF_RET|BPF_K:
+               op = "ret";
+               fmt = "#%d";
+               break;
+
+       case BPF_RET|BPF_A:
+               op = "ret";
+               fmt = "";
+               break;
+
+       case BPF_LD|BPF_W|BPF_ABS:
+               op = "ld";
+               fmt = "[%d]";
+               break;
+
+       case BPF_LD|BPF_H|BPF_ABS:
+               op = "ldh";
+               fmt = "[%d]";
+               break;
+
+       case BPF_LD|BPF_B|BPF_ABS:
+               op = "ldb";
+               fmt = "[%d]";
+               break;
+
+       case BPF_LD|BPF_W|BPF_LEN:
+               op = "ld";
+               fmt = "#pktlen";
+               break;
+
+       case BPF_LD|BPF_W|BPF_IND:
+               op = "ld";
+               fmt = "[x + %d]";
+               break;
+
+       case BPF_LD|BPF_H|BPF_IND:
+               op = "ldh";
+               fmt = "[x + %d]";
+               break;
+
+       case BPF_LD|BPF_B|BPF_IND:
+               op = "ldb";
+               fmt = "[x + %d]";
+               break;
+
+       case BPF_LD|BPF_IMM:
+               op = "ld";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_LDX|BPF_IMM:
+               op = "ldx";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_LDX|BPF_MSH|BPF_B:
+               op = "ldxb";
+               fmt = "4*([%d]&0xf)";
+               break;
+
+       case BPF_LD|BPF_MEM:
+               op = "ld";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_LDX|BPF_MEM:
+               op = "ldx";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_ST:
+               op = "st";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_STX:
+               op = "stx";
+               fmt = "M[%d]";
+               break;
+
+       case BPF_JMP|BPF_JA:
+               op = "ja";
+               fmt = "%d";
+               v = n + 1 + p->k;
+               break;
+
+       case BPF_JMP|BPF_JGT|BPF_K:
+               op = "jgt";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JGE|BPF_K:
+               op = "jge";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JEQ|BPF_K:
+               op = "jeq";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JSET|BPF_K:
+               op = "jset";
+               fmt = "#0x%x";
+               break;
+
+       case BPF_JMP|BPF_JGT|BPF_X:
+               op = "jgt";
+               fmt = "x";
+               break;
+
+       case BPF_JMP|BPF_JGE|BPF_X:
+               op = "jge";
+               fmt = "x";
+               break;
+
+       case BPF_JMP|BPF_JEQ|BPF_X:
+               op = "jeq";
+               fmt = "x";
+               break;
+
+       case BPF_JMP|BPF_JSET|BPF_X:
+               op = "jset";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_X:
+               op = "add";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_SUB|BPF_X:
+               op = "sub";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_MUL|BPF_X:
+               op = "mul";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_DIV|BPF_X:
+               op = "div";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_AND|BPF_X:
+               op = "and";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_OR|BPF_X:
+               op = "or";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_LSH|BPF_X:
+               op = "lsh";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_RSH|BPF_X:
+               op = "rsh";
+               fmt = "x";
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_K:
+               op = "add";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_SUB|BPF_K:
+               op = "sub";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_MUL|BPF_K:
+               op = "mul";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_DIV|BPF_K:
+               op = "div";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_AND|BPF_K:
+               op = "and";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_OR|BPF_K:
+               op = "or";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_LSH|BPF_K:
+               op = "lsh";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_RSH|BPF_K:
+               op = "rsh";
+               fmt = "#%d";
+               break;
+
+       case BPF_ALU|BPF_NEG:
+               op = "neg";
+               fmt = "";
+               break;
+
+       case BPF_MISC|BPF_TAX:
+               op = "tax";
+               fmt = "";
+               break;
+
+       case BPF_MISC|BPF_TXA:
+               op = "txa";
+               fmt = "";
+               break;
+       }
+       (void)sprintf(operand, fmt, v);
+       (void)sprintf(image,
+                     (BPF_CLASS(p->code) == BPF_JMP &&
+                      BPF_OP(p->code) != BPF_JA) ?
+                     "(%03d) %-8s %-16s jt %d\tjf %d"
+                     : "(%03d) %-8s %s",
+                     n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
+       return image;
+}
diff --git a/pcap/etherent.c b/pcap/etherent.c
new file mode 100644 (file)
index 0000000..3b2347e
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: etherent.c,v 1.5 1996/09/16 02:33:04 tholo Exp $      */
+
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+    "@(#) Header: etherent.c,v 1.18 95/10/07 03:08:12 leres Exp (LBL)";
+#endif
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <memory.h>
+#include <pcap.h>
+#include <pcap-namedb.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+static __inline int xdtoi(int);
+static __inline int skip_space(FILE *);
+static __inline int skip_line(FILE *);
+
+/* Hex digit to integer. */
+static __inline int
+xdtoi(c)
+       register int c;
+{
+       if (isdigit(c))
+               return c - '0';
+       else if (islower(c))
+               return c - 'a' + 10;
+       else
+               return c - 'A' + 10;
+}
+
+static __inline int
+skip_space(f)
+       FILE *f;
+{
+       int c;
+
+       do {
+               c = getc(f);
+       } while (isspace(c) && c != '\n');
+
+       return c;
+}
+
+static __inline int
+skip_line(f)
+       FILE *f;
+{
+       int c;
+
+       do
+               c = getc(f);
+       while (c != '\n' && c != EOF);
+
+       return c;
+}
+
+struct pcap_etherent *
+pcap_next_etherent(FILE *fp)
+{
+       register int c, d, i;
+       char *bp;
+       static struct pcap_etherent e;
+
+       memset((char *)&e, 0, sizeof(e));
+       do {
+               /* Find addr */
+               c = skip_space(fp);
+               if (c == '\n')
+                       continue;
+
+               /* If this is a comment, or first thing on line
+                  cannot be etehrnet address, skip the line. */
+               if (!isxdigit(c)) {
+                       c = skip_line(fp);
+                       continue;
+               }
+
+               /* must be the start of an address */
+               for (i = 0; i < 6; i += 1) {
+                       d = xdtoi(c);
+                       c = getc(fp);
+                       if (isxdigit(c)) {
+                               d <<= 4;
+                               d |= xdtoi(c);
+                               c = getc(fp);
+                       }
+                       e.addr[i] = d;
+                       if (c != ':')
+                               break;
+                       c = getc(fp);
+               }
+               if (c == EOF)
+                       break;
+
+               /* Must be whitespace */
+               if (!isspace(c)) {
+                       c = skip_line(fp);
+                       continue;
+               }
+               c = skip_space(fp);
+
+               /* hit end of line... */
+               if (c == '\n')
+                       continue;
+
+               if (c == '#') {
+                       c = skip_line(fp);
+                       continue;
+               }
+
+               /* pick up name */
+               bp = e.name;
+               /* Use 'd' to prevent buffer overflow. */
+               d = sizeof(e.name) - 1;
+               do {
+                       *bp++ = c;
+                       c = getc(fp);
+               } while (!isspace(c) && c != EOF && --d > 0);
+               *bp = '\0';
+
+               /* Eat trailing junk */
+               if (c != '\n')
+                       (void)skip_line(fp);
+
+               return &e;
+
+       } while (c != EOF);
+
+       return (NULL);
+}
diff --git a/pcap/ethertype.h b/pcap/ethertype.h
new file mode 100644 (file)
index 0000000..0a046fa
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD */
+/*     $NetBSD: ethertype.h,v 1.2 1995/03/06 11:38:17 mycroft Exp $    */
+
+/*
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) Header: ethertype.h,v 1.2 94/06/14 20:03:27 leres Exp (LBL)
+ */
+
+/* Map between Ethernet protocol types and names */
+
+/* Add other Ethernet packet types here */
+#ifndef        ETHERTYPE_SPRITE
+#define        ETHERTYPE_SPRITE        0x0500
+#endif
+#ifndef        ETHERTYPE_MOPDL
+#define        ETHERTYPE_MOPDL         0x6001
+#endif
+#ifndef        ETHERTYPE_MOPRC
+#define        ETHERTYPE_MOPRC         0x6002
+#endif
+#ifndef        ETHERTYPE_DN
+#define        ETHERTYPE_DN            0x6003
+#endif
+#ifndef        ETHERTYPE_LAT
+#define        ETHERTYPE_LAT           0x6004
+#endif
+#ifndef        ETHERTYPE_LANBRIDGE
+#define        ETHERTYPE_LANBRIDGE     0x8038
+#endif
+#ifndef        ETHERTYPE_DECDNS
+#define        ETHERTYPE_DECDNS        0x803c
+#endif
+#ifndef        ETHERTYPE_DECDTS
+#define        ETHERTYPE_DECDTS        0x803e
+#endif
+#ifndef        ETHERTYPE_VEXP
+#define        ETHERTYPE_VEXP          0x805b
+#endif
+#ifndef        ETHERTYPE_VPROD
+#define        ETHERTYPE_VPROD         0x805c
+#endif
+#ifndef        ETHERTYPE_LOOPBACK
+#define        ETHERTYPE_LOOPBACK      0x9000
+#endif
+
+#ifndef ETHERTYPE_ATALK
+#define ETHERTYPE_ATALK                0x809b /* XXX */
+#endif
+#ifndef ETHERTYPE_AARP
+#define ETHERTYPE_AARP         0x80f3
+#endif
+#ifndef ETHERTYPE_NS
+#define ETHERTYPE_NS           0x0600
+#endif
+
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP       0x8035
+#endif
+
diff --git a/pcap/gencode.c b/pcap/gencode.c
new file mode 100644 (file)
index 0000000..dfcd9e4
--- /dev/null
@@ -0,0 +1,1843 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: gencode.c,v 1.5 1996/09/16 02:33:05 tholo Exp $       */
+
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+    "@(#) Header: gencode.c,v 1.81 96/06/19 23:09:09 leres Exp (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <net/if.h>
+#include <net/bpf.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdlib.h>
+#include <memory.h>
+#include <pcap.h>
+#include <pcap-namedb.h>
+#include <setjmp.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP       0x8035
+#endif
+#ifndef        ETHERTYPE_MOPDL
+#define        ETHERTYPE_MOPDL         0x6001
+#endif
+#ifndef        ETHERTYPE_MOPRC
+#define        ETHERTYPE_MOPRC         0x6002
+#endif
+#ifndef        ETHERTYPE_DN
+#define        ETHERTYPE_DN            0x6003
+#endif
+#ifndef        ETHERTYPE_LAT
+#define        ETHERTYPE_LAT           0x6004
+#endif
+
+#define JMP(c) ((c)|BPF_JMP|BPF_K)
+
+/* Locals */
+static jmp_buf top_ctx;
+static pcap_t *bpf_pcap;
+
+/* XXX */
+#ifdef PCAP_FDDIPAD
+int    pcap_fddipad = PCAP_FDDIPAD;
+#else
+int    pcap_fddipad;
+#endif
+#ifndef DLT_ATM_RFC1483
+#define DLT_ATM_RFC1483 11
+#endif
+
+
+/* VARARGS */
+__dead void
+#if __STDC__
+bpf_error(const char *fmt, ...)
+#else
+bpf_error(fmt, va_alist)
+       const char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       if (bpf_pcap != NULL)
+               (void)vsprintf(pcap_geterr(bpf_pcap), fmt, ap);
+       va_end(ap);
+       longjmp(top_ctx, 1);
+       /* NOTREACHED */
+}
+
+static void init_linktype(int);
+
+static int alloc_reg(void);
+static void free_reg(int);
+
+static struct block *root;
+
+/*
+ * We divy out chunks of memory rather than call malloc each time so
+ * we don't have to worry about leaking memory.  It's probably
+ * not a big deal if all this memory was wasted but it this ever
+ * goes into a library that would probably not be a good idea.
+ */
+#define NCHUNKS 16
+#define CHUNK0SIZE 1024
+struct chunk {
+       u_int n_left;
+       void *m;
+};
+
+static struct chunk chunks[NCHUNKS];
+static int cur_chunk;
+
+static void *newchunk(u_int);
+static void freechunks(void);
+static __inline struct block *new_block(int);
+static __inline struct slist *new_stmt(int);
+static struct block *gen_retblk(int);
+static __inline void syntax(void);
+
+static void backpatch(struct block *, struct block *);
+static void merge(struct block *, struct block *);
+static struct block *gen_cmp(u_int, u_int, bpf_int32);
+static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
+static struct block *gen_bcmp(u_int, u_int, u_char *);
+static struct block *gen_uncond(int);
+static __inline struct block *gen_true(void);
+static __inline struct block *gen_false(void);
+static struct block *gen_linktype(int);
+static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
+static struct block *gen_ehostop(u_char *, int);
+static struct block *gen_fhostop(u_char *, int);
+static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
+static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int);
+static struct block *gen_gateway(u_char *, bpf_u_int32 **, int, int);
+static struct block *gen_ipfrag(void);
+static struct block *gen_portatom(int, bpf_int32);
+struct block *gen_portop(int, int, int);
+static struct block *gen_port(int, int, int);
+static int lookup_proto(char *, int);
+static struct block *gen_proto(int, int, int);
+static bpf_u_int32 net_mask(bpf_u_int32 *);
+static struct slist *xfer_to_x(struct arth *);
+static struct slist *xfer_to_a(struct arth *);
+static struct block *gen_len(int, int);
+
+static void *
+newchunk(n)
+       u_int n;
+{
+       struct chunk *cp;
+       int k, size;
+
+       /* XXX Round up to nearest long. */
+       n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
+
+       cp = &chunks[cur_chunk];
+       if (n > cp->n_left) {
+               ++cp, k = ++cur_chunk;
+               if (k >= NCHUNKS)
+                       bpf_error("out of memory");
+               size = CHUNK0SIZE << k;
+               cp->m = (void *)malloc(size);
+               memset((char *)cp->m, 0, size);
+               cp->n_left = size;
+               if (n > size)
+                       bpf_error("out of memory");
+       }
+       cp->n_left -= n;
+       return (void *)((char *)cp->m + cp->n_left);
+}
+
+static void
+freechunks()
+{
+       int i;
+
+       cur_chunk = 0;
+       for (i = 0; i < NCHUNKS; ++i)
+               if (chunks[i].m != NULL) {
+                       free(chunks[i].m);
+                       chunks[i].m = NULL;
+               }
+}
+
+/*
+ * A strdup whose allocations are freed after code generation is over.
+ */
+char *
+sdup(s)
+       char *s;
+{
+       int n = strlen(s) + 1;
+       char *cp = newchunk(n);
+       strcpy(cp, s);
+       return (cp);
+}
+
+static __inline struct block *
+new_block(code)
+       int code;
+{
+       struct block *p;
+
+       p = (struct block *)newchunk(sizeof(*p));
+       p->s.code = code;
+       p->head = p;
+
+       return p;
+}
+
+static __inline struct slist *
+new_stmt(code)
+       int code;
+{
+       struct slist *p;
+
+       p = (struct slist *)newchunk(sizeof(*p));
+       p->s.code = code;
+
+       return p;
+}
+
+static struct block *
+gen_retblk(v)
+       int v;
+{
+       struct block *b = new_block(BPF_RET|BPF_K);
+
+       b->s.k = v;
+       return b;
+}
+
+static __inline void
+syntax()
+{
+       bpf_error("syntax error in filter expression");
+}
+
+static bpf_u_int32 netmask;
+static int snaplen;
+
+int
+pcap_compile(pcap_t *p, struct bpf_program *program,
+            char *buf, int optimize, bpf_u_int32 mask)
+{
+       extern int n_errors;
+       int len;
+
+       n_errors = 0;
+       root = NULL;
+       bpf_pcap = p;
+       if (setjmp(top_ctx)) {
+               freechunks();
+               return (-1);
+       }
+
+       netmask = mask;
+       snaplen = pcap_snapshot(p);
+
+       lex_init(buf ? buf : "");
+       init_linktype(pcap_datalink(p));
+       (void)pcap_parse();
+
+       if (n_errors)
+               syntax();
+
+       if (root == NULL)
+               root = gen_retblk(snaplen);
+
+       if (optimize) {
+               bpf_optimize(&root);
+               if (root == NULL ||
+                   (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
+                       bpf_error("expression rejects all packets");
+       }
+       program->bf_insns = icode_to_fcode(root, &len);
+       program->bf_len = len;
+
+       freechunks();
+       return (0);
+}
+
+/*
+ * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates
+ * which of the jt and jf fields has been resolved and which is a pointer
+ * back to another unresolved block (or nil).  At least one of the fields
+ * in each block is already resolved.
+ */
+static void
+backpatch(list, target)
+       struct block *list, *target;
+{
+       struct block *next;
+
+       while (list) {
+               if (!list->sense) {
+                       next = JT(list);
+                       JT(list) = target;
+               } else {
+                       next = JF(list);
+                       JF(list) = target;
+               }
+               list = next;
+       }
+}
+
+/*
+ * Merge the lists in b0 and b1, using the 'sense' field to indicate
+ * which of jt and jf is the link.
+ */
+static void
+merge(b0, b1)
+       struct block *b0, *b1;
+{
+       register struct block **p = &b0;
+
+       /* Find end of list. */
+       while (*p)
+               p = !((*p)->sense) ? &JT(*p) : &JF(*p);
+
+       /* Concatenate the lists. */
+       *p = b1;
+}
+
+void
+finish_parse(p)
+       struct block *p;
+{
+       backpatch(p, gen_retblk(snaplen));
+       p->sense = !p->sense;
+       backpatch(p, gen_retblk(0));
+       root = p->head;
+}
+
+void
+gen_and(b0, b1)
+       struct block *b0, *b1;
+{
+       backpatch(b0, b1->head);
+       b0->sense = !b0->sense;
+       b1->sense = !b1->sense;
+       merge(b1, b0);
+       b1->sense = !b1->sense;
+       b1->head = b0->head;
+}
+
+void
+gen_or(b0, b1)
+       struct block *b0, *b1;
+{
+       b0->sense = !b0->sense;
+       backpatch(b0, b1->head);
+       b0->sense = !b0->sense;
+       merge(b1, b0);
+       b1->head = b0->head;
+}
+
+void
+gen_not(b)
+       struct block *b;
+{
+       b->sense = !b->sense;
+}
+
+static struct block *
+gen_cmp(offset, size, v)
+       u_int offset, size;
+       bpf_int32 v;
+{
+       struct slist *s;
+       struct block *b;
+
+       s = new_stmt(BPF_LD|BPF_ABS|size);
+       s->s.k = offset;
+
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+       b->s.k = v;
+
+       return b;
+}
+
+static struct block *
+gen_mcmp(offset, size, v, mask)
+       u_int offset, size;
+       bpf_int32 v;
+       bpf_u_int32 mask;
+{
+       struct block *b = gen_cmp(offset, size, v);
+       struct slist *s;
+
+       if (mask != 0xffffffff) {
+               s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               s->s.k = mask;
+               b->stmts->next = s;
+       }
+       return b;
+}
+
+static struct block *
+gen_bcmp(offset, size, v)
+       u_int offset, size;
+       u_char *v;
+{
+       struct block *b, *tmp;
+
+       b = NULL;
+       while (size >= 4) {
+               u_char *p = &v[size - 4];
+               bpf_int32 w = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+               tmp = gen_cmp(offset + size - 4, BPF_W, w);
+               if (b != NULL)
+                       gen_and(b, tmp);
+               b = tmp;
+               size -= 4;
+       }
+       while (size >= 2) {
+               u_char *p = &v[size - 2];
+               bpf_int32 w = (p[0] << 8) | p[1];
+               tmp = gen_cmp(offset + size - 2, BPF_H, w);
+               if (b != NULL)
+                       gen_and(b, tmp);
+               b = tmp;
+               size -= 2;
+       }
+       if (size > 0) {
+               tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]);
+               if (b != NULL)
+                       gen_and(b, tmp);
+               b = tmp;
+       }
+       return b;
+}
+
+/*
+ * Various code constructs need to know the layout of the data link
+ * layer.  These variables give the necessary offsets.  off_linktype
+ * is set to -1 for no encapsulation, in which case, IP is assumed.
+ */
+static u_int off_linktype;
+static u_int off_nl;
+static int linktype;
+
+static void
+init_linktype(type)
+       int type;
+{
+       linktype = type;
+
+       switch (type) {
+
+       case DLT_EN10MB:
+               off_linktype = 12;
+               off_nl = 14;
+               return;
+
+       case DLT_SLIP:
+               /*
+                * SLIP doesn't have a link level type.  The 16 byte
+                * header is hacked into our SLIP driver.
+                */
+               off_linktype = -1;
+               off_nl = 16;
+               return;
+
+       case DLT_NULL:
+               off_linktype = -1;
+               off_nl = 0;
+               return;
+
+       case DLT_PPP:
+               off_linktype = 2;
+               off_nl = 4;
+               return;
+
+       case DLT_FDDI:
+               /*
+                * FDDI doesn't really have a link-level type field.
+                * We assume that SSAP = SNAP is being used and pick
+                * out the encapsulated Ethernet type.
+                */
+               off_linktype = 19;
+#ifdef PCAP_FDDIPAD
+               off_linktype += pcap_fddipad;
+#endif
+               off_nl = 21;
+#ifdef PCAP_FDDIPAD
+               off_nl += pcap_fddipad;
+#endif
+               return;
+
+       case DLT_IEEE802:
+               off_linktype = 20;
+               off_nl = 22;
+               return;
+
+       case DLT_ATM_RFC1483:
+               /*
+                * assume routed, non-ISO PDUs
+                * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
+                */
+               off_linktype = 6;
+               off_nl = 8;
+               return;
+       }
+       bpf_error("unknown data link type 0x%x", linktype);
+       /* NOTREACHED */
+}
+
+static struct block *
+gen_uncond(rsense)
+       int rsense;
+{
+       struct block *b;
+       struct slist *s;
+
+       s = new_stmt(BPF_LD|BPF_IMM);
+       s->s.k = !rsense;
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+
+       return b;
+}
+
+static __inline struct block *
+gen_true()
+{
+       return gen_uncond(1);
+}
+
+static __inline struct block *
+gen_false()
+{
+       return gen_uncond(0);
+}
+
+static struct block *
+gen_linktype(proto)
+       int proto;
+{
+       switch (linktype) {
+       case DLT_SLIP:
+               if (proto == ETHERTYPE_IP)
+                       return gen_true();
+               else
+                       return gen_false();
+
+       case DLT_PPP:
+               if (proto == ETHERTYPE_IP)
+                       proto = 0x0021;         /* XXX - need ppp.h defs */
+               break;
+
+       case DLT_NULL:
+               /* XXX */
+               if (proto == ETHERTYPE_IP)
+                       return (gen_cmp(0, BPF_W, (bpf_int32)AF_INET));
+               else
+                       return gen_false();
+       }
+       return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
+}
+
+static struct block *
+gen_hostop(addr, mask, dir, proto, src_off, dst_off)
+       bpf_u_int32 addr;
+       bpf_u_int32 mask;
+       int dir, proto;
+       u_int src_off, dst_off;
+{
+       struct block *b0, *b1;
+       u_int offset;
+
+       switch (dir) {
+
+       case Q_SRC:
+               offset = src_off;
+               break;
+
+       case Q_DST:
+               offset = dst_off;
+               break;
+
+       case Q_AND:
+               b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
+               b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
+               b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
+               gen_or(b0, b1);
+               return b1;
+
+       default:
+               abort();
+       }
+       b0 = gen_linktype(proto);
+       b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
+       gen_and(b0, b1);
+       return b1;
+}
+
+static struct block *
+gen_ehostop(eaddr, dir)
+       u_char *eaddr;
+       int dir;
+{
+       struct block *b0, *b1;
+
+       switch (dir) {
+       case Q_SRC:
+               return gen_bcmp(6, 6, eaddr);
+
+       case Q_DST:
+               return gen_bcmp(0, 6, eaddr);
+
+       case Q_AND:
+               b0 = gen_ehostop(eaddr, Q_SRC);
+               b1 = gen_ehostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_ehostop(eaddr, Q_SRC);
+               b1 = gen_ehostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * Like gen_ehostop, but for DLT_FDDI
+ */
+static struct block *
+gen_fhostop(eaddr, dir)
+       u_char *eaddr;
+       int dir;
+{
+       struct block *b0, *b1;
+
+       switch (dir) {
+       case Q_SRC:
+#ifdef PCAP_FDDIPAD
+               return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr);
+#else
+               return gen_bcmp(6 + 1, 6, eaddr);
+#endif
+
+       case Q_DST:
+#ifdef PCAP_FDDIPAD
+               return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr);
+#else
+               return gen_bcmp(0 + 1, 6, eaddr);
+#endif
+
+       case Q_AND:
+               b0 = gen_fhostop(eaddr, Q_SRC);
+               b1 = gen_fhostop(eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_fhostop(eaddr, Q_SRC);
+               b1 = gen_fhostop(eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * This is quite tricky because there may be pad bytes in front of the
+ * DECNET header, and then there are two possible data packet formats that
+ * carry both src and dst addresses, plus 5 packet types in a format that
+ * carries only the src node, plus 2 types that use a different format and
+ * also carry just the src node.
+ *
+ * Yuck.
+ *
+ * Instead of doing those all right, we just look for data packets with
+ * 0 or 1 bytes of padding.  If you want to look at other packets, that
+ * will require a lot more hacking.
+ *
+ * To add support for filtering on DECNET "areas" (network numbers)
+ * one would want to add a "mask" argument to this routine.  That would
+ * make the filter even more inefficient, although one could be clever
+ * and not generate masking instructions if the mask is 0xFFFF.
+ */
+static struct block *
+gen_dnhostop(addr, dir, base_off)
+       bpf_u_int32 addr;
+       int dir;
+       u_int base_off;
+{
+       struct block *b0, *b1, *b2, *tmp;
+       u_int offset_lh;        /* offset if long header is received */
+       u_int offset_sh;        /* offset if short header is received */
+
+       switch (dir) {
+
+       case Q_DST:
+               offset_sh = 1;  /* follows flags */
+               offset_lh = 7;  /* flgs,darea,dsubarea,HIORD */
+               break;
+
+       case Q_SRC:
+               offset_sh = 3;  /* follows flags, dstnode */
+               offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
+               break;
+
+       case Q_AND:
+               /* Inefficient because we do our Calvinball dance twice */
+               b0 = gen_dnhostop(addr, Q_SRC, base_off);
+               b1 = gen_dnhostop(addr, Q_DST, base_off);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               /* Inefficient because we do our Calvinball dance twice */
+               b0 = gen_dnhostop(addr, Q_SRC, base_off);
+               b1 = gen_dnhostop(addr, Q_DST, base_off);
+               gen_or(b0, b1);
+               return b1;
+
+       default:
+               abort();
+       }
+       b0 = gen_linktype(ETHERTYPE_DN);
+       /* Check for pad = 1, long header case */
+       tmp = gen_mcmp(base_off + 2, BPF_H,
+           (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
+       b1 = gen_cmp(base_off + 2 + 1 + offset_lh,
+           BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b1);
+       /* Check for pad = 0, long header case */
+       tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
+       b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+       /* Check for pad = 1, short header case */
+       tmp = gen_mcmp(base_off + 2, BPF_H,
+           (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
+       b2 = gen_cmp(base_off + 2 + 1 + offset_sh,
+           BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+       /* Check for pad = 0, short header case */
+       tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
+       b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
+       gen_and(tmp, b2);
+       gen_or(b2, b1);
+
+       /* Combine with test for linktype */
+       gen_and(b0, b1);
+       return b1;
+}
+
+static struct block *
+gen_host(addr, mask, proto, dir)
+       bpf_u_int32 addr;
+       bpf_u_int32 mask;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1;
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+               b0 = gen_host(addr, mask, Q_IP, dir);
+               b1 = gen_host(addr, mask, Q_ARP, dir);
+               gen_or(b0, b1);
+               b0 = gen_host(addr, mask, Q_RARP, dir);
+               gen_or(b1, b0);
+               return b0;
+
+       case Q_IP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_IP,
+                                 off_nl + 12, off_nl + 16);
+
+       case Q_RARP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP,
+                                 off_nl + 14, off_nl + 24);
+
+       case Q_ARP:
+               return gen_hostop(addr, mask, dir, ETHERTYPE_ARP,
+                                 off_nl + 14, off_nl + 24);
+
+       case Q_TCP:
+               bpf_error("'tcp' modifier applied to host");
+
+       case Q_UDP:
+               bpf_error("'udp' modifier applied to host");
+
+       case Q_ICMP:
+               bpf_error("'icmp' modifier applied to host");
+
+       case Q_IGMP:
+               bpf_error("'igmp' modifier applied to host");
+
+       case Q_DECNET:
+               return gen_dnhostop(addr, dir, off_nl);
+
+       case Q_LAT:
+               bpf_error("LAT host filtering not implemented");
+
+       case Q_MOPDL:
+               bpf_error("MOPDL host filtering not implemented");
+
+       case Q_MOPRC:
+               bpf_error("MOPRC host filtering not implemented");
+
+       default:
+               abort();
+       }
+       /* NOTREACHED */
+}
+
+static struct block *
+gen_gateway(eaddr, alist, proto, dir)
+       u_char *eaddr;
+       bpf_u_int32 **alist;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       if (dir != 0)
+               bpf_error("direction applied to 'gateway'");
+
+       switch (proto) {
+       case Q_DEFAULT:
+       case Q_IP:
+       case Q_ARP:
+       case Q_RARP:
+               if (linktype == DLT_EN10MB)
+                       b0 = gen_ehostop(eaddr, Q_OR);
+               else if (linktype == DLT_FDDI)
+                       b0 = gen_fhostop(eaddr, Q_OR);
+               else
+                       bpf_error(
+                           "'gateway' supported only on ethernet or FDDI");
+
+               b1 = gen_host(**alist++, 0xffffffffL, proto, Q_OR);
+               while (*alist) {
+                       tmp = gen_host(**alist++, 0xffffffffL, proto, Q_OR);
+                       gen_or(b1, tmp);
+                       b1 = tmp;
+               }
+               gen_not(b1);
+               gen_and(b0, b1);
+               return b1;
+       }
+       bpf_error("illegal modifier of 'gateway'");
+       /* NOTREACHED */
+}
+
+struct block *
+gen_proto_abbrev(proto)
+       int proto;
+{
+       struct block *b0, *b1;
+
+       switch (proto) {
+
+       case Q_TCP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_TCP);
+               gen_and(b0, b1);
+               break;
+
+       case Q_UDP:
+               b0 =  gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_UDP);
+               gen_and(b0, b1);
+               break;
+
+       case Q_ICMP:
+               b0 =  gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_ICMP);
+               gen_and(b0, b1);
+               break;
+
+       case Q_IGMP:
+               b0 =  gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)2);
+               gen_and(b0, b1);
+               break;
+
+       case Q_IP:
+               b1 =  gen_linktype(ETHERTYPE_IP);
+               break;
+
+       case Q_ARP:
+               b1 =  gen_linktype(ETHERTYPE_ARP);
+               break;
+
+       case Q_RARP:
+               b1 =  gen_linktype(ETHERTYPE_REVARP);
+               break;
+
+       case Q_LINK:
+               bpf_error("link layer applied in wrong context");
+
+       case Q_DECNET:
+               b1 =  gen_linktype(ETHERTYPE_DN);
+               break;
+
+       case Q_LAT:
+               b1 =  gen_linktype(ETHERTYPE_LAT);
+               break;
+
+       case Q_MOPDL:
+               b1 =  gen_linktype(ETHERTYPE_MOPDL);
+               break;
+
+       case Q_MOPRC:
+               b1 =  gen_linktype(ETHERTYPE_MOPRC);
+               break;
+
+       default:
+               abort();
+       }
+       return b1;
+}
+
+static struct block *
+gen_ipfrag()
+{
+       struct slist *s;
+       struct block *b;
+
+       /* not ip frag */
+       s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
+       s->s.k = off_nl + 6;
+       b = new_block(JMP(BPF_JSET));
+       b->s.k = 0x1fff;
+       b->stmts = s;
+       gen_not(b);
+
+       return b;
+}
+
+static struct block *
+gen_portatom(off, v)
+       int off;
+       bpf_int32 v;
+{
+       struct slist *s;
+       struct block *b;
+
+       s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+       s->s.k = off_nl;
+
+       s->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
+       s->next->s.k = off_nl + off;
+
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+       b->s.k = v;
+
+       return b;
+}
+
+struct block *
+gen_portop(port, proto, dir)
+       int port, proto, dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* ip proto 'proto' */
+       tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);
+       b0 = gen_ipfrag();
+       gen_and(tmp, b0);
+
+       switch (dir) {
+       case Q_SRC:
+               b1 = gen_portatom(0, (bpf_int32)port);
+               break;
+
+       case Q_DST:
+               b1 = gen_portatom(2, (bpf_int32)port);
+               break;
+
+       case Q_OR:
+       case Q_DEFAULT:
+               tmp = gen_portatom(0, (bpf_int32)port);
+               b1 = gen_portatom(2, (bpf_int32)port);
+               gen_or(tmp, b1);
+               break;
+
+       case Q_AND:
+               tmp = gen_portatom(0, (bpf_int32)port);
+               b1 = gen_portatom(2, (bpf_int32)port);
+               gen_and(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+
+       return b1;
+}
+
+static struct block *
+gen_port(port, ip_proto, dir)
+       int port;
+       int ip_proto;
+       int dir;
+{
+       struct block *b0, *b1, *tmp;
+
+       /* ether proto ip */
+       b0 =  gen_linktype(ETHERTYPE_IP);
+
+       switch (ip_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+               b1 = gen_portop(port, ip_proto, dir);
+               break;
+
+       case PROTO_UNDEF:
+               tmp = gen_portop(port, IPPROTO_TCP, dir);
+               b1 = gen_portop(port, IPPROTO_UDP, dir);
+               gen_or(tmp, b1);
+               break;
+
+       default:
+               abort();
+       }
+       gen_and(b0, b1);
+       return b1;
+}
+
+static int
+lookup_proto(name, proto)
+       char *name;
+       int proto;
+{
+       int v;
+
+       switch (proto) {
+       case Q_DEFAULT:
+       case Q_IP:
+               v = pcap_nametoproto(name);
+               if (v == PROTO_UNDEF)
+                       bpf_error("unknown ip proto '%s'", name);
+               break;
+
+       case Q_LINK:
+               /* XXX should look up h/w protocol type based on linktype */
+               v = pcap_nametoeproto(name);
+               if (v == PROTO_UNDEF)
+                       bpf_error("unknown ether proto '%s'", name);
+               break;
+
+       default:
+               v = PROTO_UNDEF;
+               break;
+       }
+       return v;
+}
+
+static struct block *
+gen_proto(v, proto, dir)
+       int v;
+       int proto;
+       int dir;
+{
+       struct block *b0, *b1;
+
+       if (dir != Q_DEFAULT)
+               bpf_error("direction applied to 'proto'");
+
+       switch (proto) {
+       case Q_DEFAULT:
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ARP:
+               bpf_error("arp does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_RARP:
+               bpf_error("rarp does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_DECNET:
+               bpf_error("decnet encapsulation is not specifiable");
+               /* NOTREACHED */
+
+       case Q_LAT:
+               bpf_error("lat does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_MOPRC:
+               bpf_error("moprc does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_MOPDL:
+               bpf_error("mopdl does not encapsulate another protocol");
+               /* NOTREACHED */
+
+       case Q_LINK:
+               return gen_linktype(v);
+
+       case Q_UDP:
+               bpf_error("'udp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_TCP:
+               bpf_error("'tcp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_ICMP:
+               bpf_error("'icmp proto' is bogus");
+               /* NOTREACHED */
+
+       case Q_IGMP:
+               bpf_error("'igmp proto' is bogus");
+               /* NOTREACHED */
+
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+       /* NOTREACHED */
+}
+
+/*
+ * Left justify 'addr' and return its resulting network mask.
+ */
+static bpf_u_int32
+net_mask(addr)
+       bpf_u_int32 *addr;
+{
+       register bpf_u_int32 m = 0xffffffff;
+
+       if (*addr)
+               while ((*addr & 0xff000000) == 0)
+                       *addr <<= 8, m <<= 8;
+
+       return m;
+}
+
+struct block *
+gen_scode(name, q)
+       char *name;
+       struct qual q;
+{
+       int proto = q.proto;
+       int dir = q.dir;
+       u_char *eaddr;
+       bpf_u_int32 mask, addr, **alist;
+       struct block *b, *tmp;
+       int port, real_proto;
+
+       switch (q.addr) {
+
+       case Q_NET:
+               addr = pcap_nametonetaddr(name);
+               if (addr == 0)
+                       bpf_error("unknown network '%s'", name);
+               mask = net_mask(&addr);
+               return gen_host(addr, mask, proto, dir);
+
+       case Q_DEFAULT:
+       case Q_HOST:
+               if (proto == Q_LINK) {
+                       switch (linktype) {
+
+                       case DLT_EN10MB:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown ether host '%s'", name);
+                               return gen_ehostop(eaddr, dir);
+
+                       case DLT_FDDI:
+                               eaddr = pcap_ether_hostton(name);
+                               if (eaddr == NULL)
+                                       bpf_error(
+                                           "unknown FDDI host '%s'", name);
+                               return gen_fhostop(eaddr, dir);
+
+                       default:
+                               bpf_error(
+                       "only ethernet/FDDI supports link-level host name");
+                               break;
+                       }
+               } else if (proto == Q_DECNET) {
+                       unsigned short dn_addr = __pcap_nametodnaddr(name);
+                       /*
+                        * I don't think DECNET hosts can be multihomed, so
+                        * there is no need to build up a list of addresses
+                        */
+                       return (gen_host(dn_addr, 0, proto, dir));
+               } else {
+                       alist = pcap_nametoaddr(name);
+                       if (alist == NULL || *alist == NULL)
+                               bpf_error("unknown host '%s'", name);
+                       b = gen_host(**alist++, 0xffffffffL, proto, dir);
+                       while (*alist) {
+                               tmp = gen_host(**alist++, 0xffffffffL,
+                                              proto, dir);
+                               gen_or(b, tmp);
+                               b = tmp;
+                       }
+                       return b;
+               }
+
+       case Q_PORT:
+               if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP)
+                       bpf_error("illegal qualifier of 'port'");
+               if (pcap_nametoport(name, &port, &real_proto) == 0)
+                       bpf_error("unknown port '%s'", name);
+               if (proto == Q_UDP) {
+                       if (real_proto == IPPROTO_TCP)
+                               bpf_error("port '%s' is tcp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_UDP;
+               }
+               if (proto == Q_TCP) {
+                       if (real_proto == IPPROTO_UDP)
+                               bpf_error("port '%s' is udp", name);
+                       else
+                               /* override PROTO_UNDEF */
+                               real_proto = IPPROTO_TCP;
+               }
+               return gen_port(port, real_proto, dir);
+
+       case Q_GATEWAY:
+               eaddr = pcap_ether_hostton(name);
+               if (eaddr == NULL)
+                       bpf_error("unknown ether host: %s", name);
+
+               alist = pcap_nametoaddr(name);
+               if (alist == NULL || *alist == NULL)
+                       bpf_error("unknown host '%s'", name);
+               return gen_gateway(eaddr, alist, proto, dir);
+
+       case Q_PROTO:
+               real_proto = lookup_proto(name, proto);
+               if (real_proto >= 0)
+                       return gen_proto(real_proto, proto, dir);
+               else
+                       bpf_error("unknown protocol: %s", name);
+
+       case Q_UNDEF:
+               syntax();
+               /* NOTREACHED */
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+struct block *
+gen_ncode(v, q)
+       bpf_u_int32 v;
+       struct qual q;
+{
+       bpf_u_int32 mask;
+       int proto = q.proto;
+       int dir = q.dir;
+
+       switch (q.addr) {
+
+       case Q_DEFAULT:
+       case Q_HOST:
+       case Q_NET:
+               if (proto == Q_DECNET)
+                       return gen_host(v, 0, proto, dir);
+               else if (proto == Q_LINK) {
+                       bpf_error("illegal link layer address");
+               } else {
+                       mask = net_mask(&v);
+                       return gen_host(v, mask, proto, dir);
+               }
+
+       case Q_PORT:
+               if (proto == Q_UDP)
+                       proto = IPPROTO_UDP;
+               else if (proto == Q_TCP)
+                       proto = IPPROTO_TCP;
+               else if (proto == Q_DEFAULT)
+                       proto = PROTO_UNDEF;
+               else
+                       bpf_error("illegal qualifier of 'port'");
+
+               return gen_port((int)v, proto, dir);
+
+       case Q_GATEWAY:
+               bpf_error("'gateway' requires a name");
+               /* NOTREACHED */
+
+       case Q_PROTO:
+               return gen_proto((int)v, proto, dir);
+
+       case Q_UNDEF:
+               syntax();
+               /* NOTREACHED */
+
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+       /* NOTREACHED */
+}
+
+struct block *
+gen_ecode(eaddr, q)
+       u_char *eaddr;
+       struct qual q;
+{
+       if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
+               if (linktype == DLT_EN10MB)
+                       return gen_ehostop(eaddr, (int)q.dir);
+               if (linktype == DLT_FDDI)
+                       return gen_fhostop(eaddr, (int)q.dir);
+       }
+       bpf_error("ethernet address used in non-ether expression");
+       /* NOTREACHED */
+}
+
+void
+sappend(s0, s1)
+       struct slist *s0, *s1;
+{
+       /*
+        * This is definitely not the best way to do this, but the
+        * lists will rarely get long.
+        */
+       while (s0->next)
+               s0 = s0->next;
+       s0->next = s1;
+}
+
+static struct slist *
+xfer_to_x(a)
+       struct arth *a;
+{
+       struct slist *s;
+
+       s = new_stmt(BPF_LDX|BPF_MEM);
+       s->s.k = a->regno;
+       return s;
+}
+
+static struct slist *
+xfer_to_a(a)
+       struct arth *a;
+{
+       struct slist *s;
+
+       s = new_stmt(BPF_LD|BPF_MEM);
+       s->s.k = a->regno;
+       return s;
+}
+
+struct arth *
+gen_load(proto, index, size)
+       int proto;
+       struct arth *index;
+       int size;
+{
+       struct slist *s, *tmp;
+       struct block *b;
+       int regno = alloc_reg();
+
+       free_reg(index->regno);
+       switch (size) {
+
+       default:
+               bpf_error("data size must be 1, 2, or 4");
+
+       case 1:
+               size = BPF_B;
+               break;
+
+       case 2:
+               size = BPF_H;
+               break;
+
+       case 4:
+               size = BPF_W;
+               break;
+       }
+       switch (proto) {
+       default:
+               bpf_error("unsupported index operation");
+
+       case Q_LINK:
+               s = xfer_to_x(index);
+               tmp = new_stmt(BPF_LD|BPF_IND|size);
+               sappend(s, tmp);
+               sappend(index->s, s);
+               break;
+
+       case Q_IP:
+       case Q_ARP:
+       case Q_RARP:
+       case Q_DECNET:
+       case Q_LAT:
+       case Q_MOPRC:
+       case Q_MOPDL:
+               /* XXX Note that we assume a fixed link link header here. */
+               s = xfer_to_x(index);
+               tmp = new_stmt(BPF_LD|BPF_IND|size);
+               tmp->s.k = off_nl;
+               sappend(s, tmp);
+               sappend(index->s, s);
+
+               b = gen_proto_abbrev(proto);
+               if (index->b)
+                       gen_and(index->b, b);
+               index->b = b;
+               break;
+
+       case Q_TCP:
+       case Q_UDP:
+       case Q_ICMP:
+       case Q_IGMP:
+               s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+               s->s.k = off_nl;
+               sappend(s, xfer_to_a(index));
+               sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
+               sappend(s, new_stmt(BPF_MISC|BPF_TAX));
+               sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
+               tmp->s.k = off_nl;
+               sappend(index->s, s);
+
+               gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
+               if (index->b)
+                       gen_and(index->b, b);
+               index->b = b;
+               break;
+       }
+       index->regno = regno;
+       s = new_stmt(BPF_ST);
+       s->s.k = regno;
+       sappend(index->s, s);
+
+       return index;
+}
+
+struct block *
+gen_relation(code, a0, a1, reversed)
+       int code;
+       struct arth *a0, *a1;
+       int reversed;
+{
+       struct slist *s0, *s1, *s2;
+       struct block *b, *tmp;
+
+       s0 = xfer_to_x(a1);
+       s1 = xfer_to_a(a0);
+       s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
+       b = new_block(JMP(code));
+       if (code == BPF_JGT || code == BPF_JGE) {
+               reversed = !reversed;
+               b->s.k = 0x80000000;
+       }
+       if (reversed)
+               gen_not(b);
+
+       sappend(s1, s2);
+       sappend(s0, s1);
+       sappend(a1->s, s0);
+       sappend(a0->s, a1->s);
+
+       b->stmts = a0->s;
+
+       free_reg(a0->regno);
+       free_reg(a1->regno);
+
+       /* 'and' together protocol checks */
+       if (a0->b) {
+               if (a1->b) {
+                       gen_and(a0->b, tmp = a1->b);
+               }
+               else
+                       tmp = a0->b;
+       } else
+               tmp = a1->b;
+
+       if (tmp)
+               gen_and(tmp, b);
+
+       return b;
+}
+
+struct arth *
+gen_loadlen()
+{
+       int regno = alloc_reg();
+       struct arth *a = (struct arth *)newchunk(sizeof(*a));
+       struct slist *s;
+
+       s = new_stmt(BPF_LD|BPF_LEN);
+       s->next = new_stmt(BPF_ST);
+       s->next->s.k = regno;
+       a->s = s;
+       a->regno = regno;
+
+       return a;
+}
+
+struct arth *
+gen_loadi(val)
+       int val;
+{
+       struct arth *a;
+       struct slist *s;
+       int reg;
+
+       a = (struct arth *)newchunk(sizeof(*a));
+
+       reg = alloc_reg();
+
+       s = new_stmt(BPF_LD|BPF_IMM);
+       s->s.k = val;
+       s->next = new_stmt(BPF_ST);
+       s->next->s.k = reg;
+       a->s = s;
+       a->regno = reg;
+
+       return a;
+}
+
+struct arth *
+gen_neg(a)
+       struct arth *a;
+{
+       struct slist *s;
+
+       s = xfer_to_a(a);
+       sappend(a->s, s);
+       s = new_stmt(BPF_ALU|BPF_NEG);
+       s->s.k = 0;
+       sappend(a->s, s);
+       s = new_stmt(BPF_ST);
+       s->s.k = a->regno;
+       sappend(a->s, s);
+
+       return a;
+}
+
+struct arth *
+gen_arth(code, a0, a1)
+       int code;
+       struct arth *a0, *a1;
+{
+       struct slist *s0, *s1, *s2;
+
+       s0 = xfer_to_x(a1);
+       s1 = xfer_to_a(a0);
+       s2 = new_stmt(BPF_ALU|BPF_X|code);
+
+       sappend(s1, s2);
+       sappend(s0, s1);
+       sappend(a1->s, s0);
+       sappend(a0->s, a1->s);
+
+       free_reg(a1->regno);
+
+       s0 = new_stmt(BPF_ST);
+       a0->regno = s0->s.k = alloc_reg();
+       sappend(a0->s, s0);
+
+       return a0;
+}
+
+/*
+ * Here we handle simple allocation of the scratch registers.
+ * If too many registers are alloc'd, the allocator punts.
+ */
+static int regused[BPF_MEMWORDS];
+static int curreg;
+
+/*
+ * Return the next free register.
+ */
+static int
+alloc_reg()
+{
+       int n = BPF_MEMWORDS;
+
+       while (--n >= 0) {
+               if (regused[curreg])
+                       curreg = (curreg + 1) % BPF_MEMWORDS;
+               else {
+                       regused[curreg] = 1;
+                       return curreg;
+               }
+       }
+       bpf_error("too many registers needed to evaluate expression");
+       /* NOTREACHED */
+}
+
+/*
+ * Return a register to the table so it can
+ * be used later.
+ */
+static void
+free_reg(n)
+       int n;
+{
+       regused[n] = 0;
+}
+
+static struct block *
+gen_len(jmp, n)
+       int jmp, n;
+{
+       struct slist *s;
+       struct block *b;
+
+       s = new_stmt(BPF_LD|BPF_LEN);
+       b = new_block(JMP(jmp));
+       b->stmts = s;
+       b->s.k = n;
+
+       return b;
+}
+
+struct block *
+gen_greater(n)
+       int n;
+{
+       return gen_len(BPF_JGE, n);
+}
+
+struct block *
+gen_less(n)
+       int n;
+{
+       struct block *b;
+
+       b = gen_len(BPF_JGT, n);
+       gen_not(b);
+
+       return b;
+}
+
+struct block *
+gen_byteop(op, idx, val)
+       int op, idx, val;
+{
+       struct block *b;
+       struct slist *s;
+
+       switch (op) {
+       default:
+               abort();
+
+       case '=':
+               return gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
+
+       case '<':
+               b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
+               b->s.code = JMP(BPF_JGE);
+               gen_not(b);
+               return b;
+
+       case '>':
+               b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val);
+               b->s.code = JMP(BPF_JGT);
+               return b;
+
+       case '|':
+               s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
+               break;
+
+       case '&':
+               s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+               break;
+       }
+       s->s.k = val;
+       b = new_block(JMP(BPF_JEQ));
+       b->stmts = s;
+       gen_not(b);
+
+       return b;
+}
+
+struct block *
+gen_broadcast(proto)
+       int proto;
+{
+       bpf_u_int32 hostmask;
+       struct block *b0, *b1, *b2;
+       static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+       case Q_LINK:
+               if (linktype == DLT_EN10MB)
+                       return gen_ehostop(ebroadcast, Q_DST);
+               if (linktype == DLT_FDDI)
+                       return gen_fhostop(ebroadcast, Q_DST);
+               bpf_error("not a broadcast link");
+               break;
+
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               hostmask = ~netmask;
+               b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask);
+               b2 = gen_mcmp(off_nl + 16, BPF_W,
+                             (bpf_int32)(~0 & hostmask), hostmask);
+               gen_or(b1, b2);
+               gen_and(b0, b2);
+               return b2;
+       }
+       bpf_error("only ether/ip broadcast filters supported");
+}
+
+struct block *
+gen_multicast(proto)
+       int proto;
+{
+       register struct block *b0, *b1;
+       register struct slist *s;
+
+       switch (proto) {
+
+       case Q_DEFAULT:
+       case Q_LINK:
+               if (linktype == DLT_EN10MB) {
+                       /* ether[0] & 1 != 0 */
+                       s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+                       s->s.k = 0;
+                       b0 = new_block(JMP(BPF_JSET));
+                       b0->s.k = 1;
+                       b0->stmts = s;
+                       return b0;
+               }
+
+               if (linktype == DLT_FDDI) {
+                       /* XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX */
+                       /* fddi[1] & 1 != 0 */
+                       s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+                       s->s.k = 1;
+                       b0 = new_block(JMP(BPF_JSET));
+                       b0->s.k = 1;
+                       b0->stmts = s;
+                       return b0;
+               }
+               /* Link not known to support multicasts */
+               break;
+
+       case Q_IP:
+               b0 = gen_linktype(ETHERTYPE_IP);
+               b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
+               b1->s.code = JMP(BPF_JGE);
+               gen_and(b0, b1);
+               return b1;
+       }
+       bpf_error("only IP multicast filters supported on ethernet/FDDI");
+}
+
+/*
+ * generate command for inbound/outbound.  It's here so we can
+ * make it link-type specific.  'dir' = 0 implies "inbound",
+ * = 1 implies "outbound".
+ */
+struct block *
+gen_inbound(dir)
+       int dir;
+{
+       register struct block *b0;
+
+       b0 = gen_relation(BPF_JEQ,
+                         gen_load(Q_LINK, gen_loadi(0), 1),
+                         gen_loadi(0),
+                         dir);
+       return (b0);
+}
diff --git a/pcap/gencode.h b/pcap/gencode.h
new file mode 100644 (file)
index 0000000..33cb995
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: gencode.h,v 1.4 1996/07/12 13:19:08 mickey Exp $      */
+
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) Header: gencode.h,v 1.33 96/06/23 02:21:09 leres Exp (LBL)
+ */
+
+/* Address qualifiers. */
+
+#define Q_HOST         1
+#define Q_NET          2
+#define Q_PORT         3
+#define Q_GATEWAY      4
+#define Q_PROTO                5
+
+/* Protocol qualifiers. */
+
+#define Q_LINK         1
+#define Q_IP           2
+#define Q_ARP          3
+#define Q_RARP         4
+#define Q_TCP          5
+#define Q_UDP          6
+#define Q_ICMP         7
+#define Q_IGMP         8
+
+#define        Q_DECNET        9
+#define        Q_LAT           10
+#define        Q_MOPRC         11
+#define        Q_MOPDL         12
+
+/* Directional qualifiers. */
+
+#define Q_SRC          1
+#define Q_DST          2
+#define Q_OR           3
+#define Q_AND          4
+
+#define Q_DEFAULT      0
+#define Q_UNDEF                255
+
+struct stmt {
+       int code;
+       bpf_int32 k;
+};
+
+struct slist {
+       struct stmt s;
+       struct slist *next;
+};
+
+/* 
+ * A bit vector to represent definition sets.  We assume TOT_REGISTERS
+ * is smaller than 8*sizeof(atomset).
+ */
+typedef bpf_u_int32 atomset;
+#define ATOMMASK(n) (1 << (n))
+#define ATOMELEM(d, n) (d & ATOMMASK(n))
+
+/*
+ * An unbounded set.
+ */
+typedef bpf_u_int32 *uset;
+
+/*
+ * Total number of atomic entities, including accumulator (A) and index (X).
+ * We treat all these guys similarly during flow analysis.
+ */
+#define N_ATOMS (BPF_MEMWORDS+2)
+
+struct edge {
+       int id;
+       int code;
+       uset edom;
+       struct block *succ;
+       struct block *pred;
+       struct edge *next;      /* link list of incoming edges for a node */
+};
+
+struct block {
+       int id;
+       struct slist *stmts;    /* side effect stmts */
+       struct stmt s;          /* branch stmt */
+       int mark;
+       int longjt;             /* jt branch requires long jump */
+       int longjf;             /* jf branch requires long jump */
+       int level;
+       int offset;
+       int sense;
+       struct edge et;
+       struct edge ef;
+       struct block *head;
+       struct block *link;     /* link field used by optimizer */
+       uset dom;
+       uset closure;
+       struct edge *in_edges;
+       atomset def, kill;
+       atomset in_use;
+       atomset out_use;
+       int oval;
+       int val[N_ATOMS];
+};
+
+struct arth {
+       struct block *b;        /* protocol checks */
+       struct slist *s;        /* stmt list */
+       int regno;              /* virtual register number of result */
+};
+
+struct qual {
+       unsigned char addr;
+       unsigned char proto;
+       unsigned char dir;
+       unsigned char pad;
+};
+
+struct arth *gen_loadi(int);
+struct arth *gen_load(int, struct arth *, int);
+struct arth *gen_loadlen(void);
+struct arth *gen_neg(struct arth *);
+struct arth *gen_arth(int, struct arth *, struct arth *);
+
+void gen_and(struct block *, struct block *);
+void gen_or(struct block *, struct block *);
+void gen_not(struct block *);
+
+struct block *gen_scode(char *, struct qual);
+struct block *gen_ecode(u_char *, struct qual);
+struct block *gen_ncode(bpf_u_int32, struct qual);
+struct block *gen_proto_abbrev(int);
+struct block *gen_relation(int, struct arth *, struct arth *, int);
+struct block *gen_less(int);
+struct block *gen_greater(int);
+struct block *gen_byteop(int, int, int);
+struct block *gen_broadcast(int);
+struct block *gen_multicast(int);
+struct block *gen_inbound(int);
+
+void bpf_optimize(struct block **);
+#if __STDC__
+__dead void bpf_error(const char *, ...)
+    __attribute__((volatile, format (printf, 1, 2)));
+#endif
+
+void finish_parse(struct block *);
+char *sdup(char *);
+
+struct bpf_insn *icode_to_fcode(struct block *, int *);
+int pcap_parse(void);
+void lex_init(char *);
+void sappend(struct slist *, struct slist *);
+
+/* XXX */
+#define JT(b)  ((b)->et.succ)
+#define JF(b)  ((b)->ef.succ)
diff --git a/pcap/grammar.y b/pcap/grammar.y
new file mode 100644 (file)
index 0000000..529ca97
--- /dev/null
@@ -0,0 +1,280 @@
+%{
+/*     $OpenBSD: grammar.y,v 1.4 1996/07/12 13:19:09 mickey Exp $      */
+
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#ifndef lint
+static char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/pcap/grammar.y,v 1.1.1.1 1999/05/02 03:57:54 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <net/if.h>
+#include <net/bpf.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdio.h>
+#include <pcap.h>
+#include <pcap-namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+#include "gencode.h"
+
+#define QSET(q, p, d, a) (q).proto = (p),\
+                        (q).dir = (d),\
+                        (q).addr = (a)
+
+int n_errors = 0;
+
+static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+
+static void
+yyerror(char *msg)
+{
+       ++n_errors;
+       bpf_error(msg);
+       /* NOTREACHED */
+}
+
+#ifndef YYBISON
+int yyparse(void);
+
+int
+pcap_parse()
+{
+       return (yyparse());
+}
+#endif
+
+%}
+
+%union {
+       int i;
+       u_long h;
+       u_char *e;
+       char *s;
+       struct stmt *stmt;
+       struct arth *a;
+       struct {
+               struct qual q;
+               struct block *b;
+       } blk;
+       struct block *rblk;
+}
+
+%type  <blk>   expr id nid pid term rterm qid
+%type  <blk>   head
+%type  <i>     pqual dqual aqual ndaqual
+%type  <a>     arth narth
+%type  <i>     byteop pname pnum relop irelop
+%type  <blk>   and or paren not null prog
+%type  <rblk>  other
+
+%token  DST SRC HOST GATEWAY
+%token  NET PORT LESS GREATER PROTO BYTE
+%token  ARP RARP IP TCP UDP ICMP IGMP
+%token  DECNET LAT MOPRC MOPDL
+%token  TK_BROADCAST TK_MULTICAST
+%token  NUM INBOUND OUTBOUND
+%token  LINK
+%token GEQ LEQ NEQ
+%token ID EID HID
+%token LSH RSH
+%token  LEN
+
+%type  <s> ID
+%type  <e> EID
+%type  <h> HID
+%type  <i> NUM
+
+%left OR AND
+%nonassoc  '!'
+%left '|'
+%left '&'
+%left LSH RSH
+%left '+' '-'
+%left '*' '/'
+%nonassoc UMINUS
+%%
+prog:    null expr
+{
+       finish_parse($2.b);
+}
+       | null
+       ;
+null:    /* null */            { $$.q = qerr; }
+       ;
+expr:    term
+       | expr and term         { gen_and($1.b, $3.b); $$ = $3; }
+       | expr and id           { gen_and($1.b, $3.b); $$ = $3; }
+       | expr or term          { gen_or($1.b, $3.b); $$ = $3; }
+       | expr or id            { gen_or($1.b, $3.b); $$ = $3; }
+       ;
+and:     AND                   { $$ = $<blk>0; }
+       ;
+or:      OR                    { $$ = $<blk>0; }
+       ;
+id:      nid
+       | pnum                  { $$.b = gen_ncode((u_long)$1,
+                                                  $$.q = $<blk>0.q); }
+       | paren pid ')'         { $$ = $2; }
+       ;
+nid:     ID                    { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
+       | HID                   {
+                                 /* Decide how to parse HID based on proto */
+                                 $$.q = $<blk>0.q;
+                                 switch ($$.q.proto) {
+                                 case Q_DECNET:
+                                       $$.b =
+                                           gen_ncode(__pcap_atodn((char *)$1),
+                                           $$.q);
+                                       break;
+                                 default:
+                                       $$.b =
+                                           gen_ncode(__pcap_atoin((char *)$1),
+                                           $$.q);
+                                       break;
+                                 }
+                               }
+       | EID                   { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
+       | not id                { gen_not($2.b); $$ = $2; }
+       ;
+not:     '!'                   { $$ = $<blk>0; }
+       ;
+paren:   '('                   { $$ = $<blk>0; }
+       ;
+pid:     nid
+       | qid and id            { gen_and($1.b, $3.b); $$ = $3; }
+       | qid or id             { gen_or($1.b, $3.b); $$ = $3; }
+       ;
+qid:     pnum                  { $$.b = gen_ncode((u_long)$1,
+                                                  $$.q = $<blk>0.q); }
+       | pid
+       ;
+term:    rterm
+       | not term              { gen_not($2.b); $$ = $2; }
+       ;
+head:    pqual dqual aqual     { QSET($$.q, $1, $2, $3); }
+       | pqual dqual           { QSET($$.q, $1, $2, Q_DEFAULT); }
+       | pqual aqual           { QSET($$.q, $1, Q_DEFAULT, $2); }
+       | pqual PROTO           { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
+       | pqual ndaqual         { QSET($$.q, $1, Q_DEFAULT, $2); }
+       ;
+rterm:   head id               { $$ = $2; }
+       | paren expr ')'        { $$.b = $2.b; $$.q = $1.q; }
+       | pname                 { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
+       | arth relop arth       { $$.b = gen_relation($2, $1, $3, 0);
+                                 $$.q = qerr; }
+       | arth irelop arth      { $$.b = gen_relation($2, $1, $3, 1);
+                                 $$.q = qerr; }
+       | other                 { $$.b = $1; $$.q = qerr; }
+       ;
+/* protocol level qualifiers */
+pqual:   pname
+       |                       { $$ = Q_DEFAULT; }
+       ;
+/* 'direction' qualifiers */
+dqual:   SRC                   { $$ = Q_SRC; }
+       | DST                   { $$ = Q_DST; }
+       | SRC OR DST            { $$ = Q_OR; }
+       | DST OR SRC            { $$ = Q_OR; }
+       | SRC AND DST           { $$ = Q_AND; }
+       | DST AND SRC           { $$ = Q_AND; }
+       ;
+/* address type qualifiers */
+aqual:   HOST                  { $$ = Q_HOST; }
+       | NET                   { $$ = Q_NET; }
+       | PORT                  { $$ = Q_PORT; }
+       ;
+/* non-directional address type qualifiers */
+ndaqual:  GATEWAY              { $$ = Q_GATEWAY; }
+       ;
+pname:   LINK                  { $$ = Q_LINK; }
+       | IP                    { $$ = Q_IP; }
+       | ARP                   { $$ = Q_ARP; }
+       | RARP                  { $$ = Q_RARP; }
+       | TCP                   { $$ = Q_TCP; }
+       | UDP                   { $$ = Q_UDP; }
+       | ICMP                  { $$ = Q_ICMP; }
+       | IGMP                  { $$ = Q_IGMP; }
+       | DECNET                { $$ = Q_DECNET; }
+       | LAT                   { $$ = Q_LAT; }
+       | MOPDL                 { $$ = Q_MOPDL; }
+       | MOPRC                 { $$ = Q_MOPRC; }
+       ;
+other:   pqual TK_BROADCAST    { $$ = gen_broadcast($1); }
+       | pqual TK_MULTICAST    { $$ = gen_multicast($1); }
+       | LESS NUM              { $$ = gen_less($2); }
+       | GREATER NUM           { $$ = gen_greater($2); }
+       | BYTE NUM byteop NUM   { $$ = gen_byteop($3, $2, $4); }
+       | INBOUND               { $$ = gen_inbound(0); }
+       | OUTBOUND              { $$ = gen_inbound(1); }
+       ;
+relop:   '>'                   { $$ = BPF_JGT; }
+       | GEQ                   { $$ = BPF_JGE; }
+       | '='                   { $$ = BPF_JEQ; }
+       ;
+irelop:          LEQ                   { $$ = BPF_JGT; }
+       | '<'                   { $$ = BPF_JGE; }
+       | NEQ                   { $$ = BPF_JEQ; }
+       ;
+arth:    pnum                  { $$ = gen_loadi($1); }
+       | narth
+       ;
+narth:   pname '[' arth ']'            { $$ = gen_load($1, $3, 1); }
+       | pname '[' arth ':' NUM ']'    { $$ = gen_load($1, $3, $5); }
+       | arth '+' arth                 { $$ = gen_arth(BPF_ADD, $1, $3); }
+       | arth '-' arth                 { $$ = gen_arth(BPF_SUB, $1, $3); }
+       | arth '*' arth                 { $$ = gen_arth(BPF_MUL, $1, $3); }
+       | arth '/' arth                 { $$ = gen_arth(BPF_DIV, $1, $3); }
+       | arth '&' arth                 { $$ = gen_arth(BPF_AND, $1, $3); }
+       | arth '|' arth                 { $$ = gen_arth(BPF_OR, $1, $3); }
+       | arth LSH arth                 { $$ = gen_arth(BPF_LSH, $1, $3); }
+       | arth RSH arth                 { $$ = gen_arth(BPF_RSH, $1, $3); }
+       | '-' arth %prec UMINUS         { $$ = gen_neg($2); }
+       | paren narth ')'               { $$ = $2; }
+       | LEN                           { $$ = gen_loadlen(); }
+       ;
+byteop:          '&'                   { $$ = '&'; }
+       | '|'                   { $$ = '|'; }
+       | '<'                   { $$ = '<'; }
+       | '>'                   { $$ = '>'; }
+       | '='                   { $$ = '='; }
+       ;
+pnum:    NUM
+       | paren pnum ')'        { $$ = $2; }
+       ;
+%%
diff --git a/pcap/inet.c b/pcap/inet.c
new file mode 100644 (file)
index 0000000..50afec5
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: inet.c,v 1.6 1997/01/24 19:17:25 deraadt Exp $        */
+
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+    "@(#) Header: inet.c,v 1.16 96/06/23 14:28:22 leres Exp (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pcap.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+/* Not all systems have IFF_LOOPBACK */
+#ifdef IFF_LOOPBACK
+#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
+#else
+#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0)
+#endif
+
+/*
+ * Return the name of a network interface attached to the system, or NULL
+ * if none can be found.  The interface must be configured up; the
+ * lowest unit number is preferred; loopback is ignored.
+ */
+char *
+pcap_lookupdev(errbuf)
+       register char *errbuf;
+{
+       register int fd, minunit, n;
+       register char *cp, *ibuf = NULL;
+       register struct ifreq *ifrp, *ifend, *ifnext, *mp;
+       struct ifconf ifc;
+       struct ifreq ifr;
+       static char device[sizeof(ifrp->ifr_name) + 1];
+       int len = 8192;
+
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
+               return (NULL);
+       }
+       while (1) {
+               ifc.ifc_len = len;
+               ifc.ifc_buf = ibuf = realloc(ibuf, len);
+               if (ibuf == NULL) {
+                       close(fd);
+                       return (NULL);
+               }
+               if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) {
+                       (void)close(fd);
+                       free(ibuf);
+                       return (NULL);
+               }
+               if (ifc.ifc_len + sizeof(ifr) < len)
+                       break;
+               len *= 2;
+       }
+
+       ifrp = (struct ifreq *)ibuf;
+       ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
+
+       mp = NULL;
+       minunit = 666;
+       for (; ifrp < ifend; ifrp = ifnext) {
+#if BSD - 0 >= 199006
+               n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
+               if (n < sizeof(*ifrp))
+                       ifnext = ifrp + 1;
+               else
+                       ifnext = (struct ifreq *)((char *)ifrp + n);
+               if (ifrp->ifr_addr.sa_family != AF_INET)
+                       continue;
+#else
+               ifnext = ifrp + 1;
+#endif
+               /*
+                * Need a template to preserve address info that is
+                * used below to locate the next entry.  (Otherwise,
+                * SIOCGIFFLAGS stomps over it because the requests
+                * are returned in a union.)
+                */
+               strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
+               if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+                       (void)sprintf(errbuf, "SIOCGIFFLAGS: %s",
+                           pcap_strerror(errno));
+                       (void)close(fd);
+                       free(ibuf);
+                       return (NULL);
+               }
+
+               /* Must be up and not the loopback */
+               if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr))
+                       continue;
+
+               for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
+                       continue;
+               n = atoi(cp);
+               if (n < minunit) {
+                       minunit = n;
+                       mp = ifrp;
+               }
+       }
+       free(ibuf);
+       (void)close(fd);
+       if (mp == NULL) {
+               (void)strcpy(errbuf, "no suitable device found");
+               return (NULL);
+       }
+
+       (void)strncpy(device, mp->ifr_name, sizeof(device) - 1);
+       device[sizeof(device) - 1] = '\0';
+       return (device);
+}
+
+int
+pcap_lookupnet(device, netp, maskp, errbuf)
+       register char *device;
+       register bpf_u_int32 *netp, *maskp;
+       register char *errbuf;
+{
+       register int fd;
+       register struct sockaddr_in *sin;
+       struct ifreq ifr;
+
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (fd < 0) {
+               (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       memset(&ifr, 0, sizeof(ifr));
+#ifdef linux
+       /* XXX Work around Linux kernel bug */
+       ifr.ifr_addr.sa_family = AF_INET;
+#endif
+       (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
+               (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s",
+                   device, pcap_strerror(errno));
+               (void)close(fd);
+               return (-1);
+       }
+       sin = (struct sockaddr_in *)&ifr.ifr_addr;
+       *netp = sin->sin_addr.s_addr;
+       if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
+               (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s",
+                   device, pcap_strerror(errno));
+               (void)close(fd);
+               return (-1);
+       }
+       (void)close(fd);
+       *maskp = sin->sin_addr.s_addr;
+       if (*maskp == 0) {
+               if (IN_CLASSA(*netp))
+                       *maskp = IN_CLASSA_NET;
+               else if (IN_CLASSB(*netp))
+                       *maskp = IN_CLASSB_NET;
+               else if (IN_CLASSC(*netp))
+                       *maskp = IN_CLASSC_NET;
+               else {
+                       (void)sprintf(errbuf, "inet class for 0x%x unknown",
+                           *netp);
+                       return (-1);
+               }
+       }
+       *netp &= *maskp;
+       return (0);
+}
diff --git a/pcap/nametoaddr.c b/pcap/nametoaddr.c
new file mode 100644 (file)
index 0000000..3ce8008
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: nametoaddr.c,v 1.5 1996/09/16 02:33:06 tholo Exp $    */
+
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Name to id translation routines used by the scanner.
+ * These functions are not time critical.
+ */
+
+#ifndef lint
+static char rcsid[] =
+    "@(#) Header: nametoaddr.c,v 1.38 96/06/17 02:42:50 leres Exp (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <netdb.h>
+#include <pcap.h>
+#include <pcap-namedb.h>
+#include <stdio.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+#include "gencode.h"
+
+#ifndef NTOHL
+#define NTOHL(x) (x) = ntohl(x)
+#define NTOHS(x) (x) = ntohs(x)
+#endif
+
+static __inline int xdtoi(int);
+
+/*
+ *  Convert host name to internet address.
+ *  Return 0 upon failure.
+ */
+bpf_u_int32 **
+pcap_nametoaddr(const char *name)
+{
+#ifndef h_addr
+       static bpf_u_int32 *hlist[2];
+#endif
+       bpf_u_int32 **p;
+       struct hostent *hp;
+
+       if ((hp = gethostbyname(name)) != NULL) {
+#ifndef h_addr
+               hlist[0] = (bpf_u_int32 *)hp->h_addr;
+               NTOHL(hp->h_addr);
+               return hlist;
+#else
+               for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
+                       NTOHL(**p);
+               return (bpf_u_int32 **)hp->h_addr_list;
+#endif
+       }
+       else
+               return 0;
+}
+
+/*
+ *  Convert net name to internet address.
+ *  Return 0 upon failure.
+ */
+bpf_u_int32
+pcap_nametonetaddr(const char *name)
+{
+       struct netent *np;
+
+       if ((np = getnetbyname(name)) != NULL)
+               return np->n_net;
+       else
+               return 0;
+}
+
+/*
+ * Convert a port name to its port and protocol numbers.
+ * We assume only TCP or UDP.
+ * Return 0 upon failure.
+ */
+int
+pcap_nametoport(const char *name, int *port, int *proto)
+{
+       struct servent *sp;
+       char *other;
+
+       sp = getservbyname(name, (char *)0);
+       if (sp != NULL) {
+               NTOHS(sp->s_port);
+               *port = sp->s_port;
+               *proto = pcap_nametoproto(sp->s_proto);
+               /*
+                * We need to check /etc/services for ambiguous entries.
+                * If we find the ambiguous entry, and it has the
+                * same port number, change the proto to PROTO_UNDEF
+                * so both TCP and UDP will be checked.
+                */
+               if (*proto == IPPROTO_TCP)
+                       other = "udp";
+               else
+                       other = "tcp";
+
+               sp = getservbyname(name, other);
+               if (sp != 0) {
+                       NTOHS(sp->s_port);
+#ifdef notdef
+                       if (*port != sp->s_port)
+                               /* Can't handle ambiguous names that refer
+                                  to different port numbers. */
+                               warning("ambiguous port %s in /etc/services",
+                                       name);
+#endif
+                       *proto = PROTO_UNDEF;
+               }
+               return 1;
+       }
+#if defined(ultrix) || defined(__osf__)
+       /* Special hack in case NFS isn't in /etc/services */
+       if (strcmp(name, "nfs") == 0) {
+               *port = 2049;
+               *proto = PROTO_UNDEF;
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+int
+pcap_nametoproto(const char *str)
+{
+       struct protoent *p;
+
+       p = getprotobyname(str);
+       if (p != 0)
+               return p->p_proto;
+       else
+               return PROTO_UNDEF;
+}
+
+#include "ethertype.h"
+
+struct eproto {
+       char *s;
+       u_short p;
+};
+
+/* Static data base of ether protocol types. */
+struct eproto eproto_db[] = {
+       { "pup", ETHERTYPE_PUP },
+       { "xns", ETHERTYPE_NS },
+       { "ip", ETHERTYPE_IP },
+       { "arp", ETHERTYPE_ARP },
+       { "rarp", ETHERTYPE_REVARP },
+       { "sprite", ETHERTYPE_SPRITE },
+       { "mopdl", ETHERTYPE_MOPDL },
+       { "moprc", ETHERTYPE_MOPRC },
+       { "decnet", ETHERTYPE_DN },
+       { "lat", ETHERTYPE_LAT },
+       { "lanbridge", ETHERTYPE_LANBRIDGE },
+       { "vexp", ETHERTYPE_VEXP },
+       { "vprod", ETHERTYPE_VPROD },
+       { "atalk", ETHERTYPE_ATALK },
+       { "atalkarp", ETHERTYPE_AARP },
+       { "loopback", ETHERTYPE_LOOPBACK },
+       { "decdts", ETHERTYPE_DECDTS },
+       { "decdns", ETHERTYPE_DECDNS },
+       { (char *)0, 0 }
+};
+
+int
+pcap_nametoeproto(const char *s)
+{
+       struct eproto *p = eproto_db;
+
+       while (p->s != 0) {
+               if (strcmp(p->s, s) == 0)
+                       return p->p;
+               p += 1;
+       }
+       return PROTO_UNDEF;
+}
+
+/* Hex digit to integer. */
+static __inline int
+xdtoi(c)
+       register int c;
+{
+       if (isdigit(c))
+               return c - '0';
+       else if (islower(c))
+               return c - 'a' + 10;
+       else
+               return c - 'A' + 10;
+}
+
+bpf_u_int32
+__pcap_atoin(const char *s)
+{
+       bpf_u_int32 addr = 0;
+       u_int n;
+
+       while (1) {
+               n = 0;
+               while (*s && *s != '.')
+                       n = n * 10 + *s++ - '0';
+               addr <<= 8;
+               addr |= n & 0xff;
+               if (*s == '\0')
+                       return addr;
+               ++s;
+       }
+       /* NOTREACHED */
+}
+
+bpf_u_int32
+__pcap_atodn(const char *s)
+{
+#define AREASHIFT 10
+#define AREAMASK 0176000
+#define NODEMASK 01777
+
+       bpf_u_int32 addr = 0;
+       u_int node, area;
+
+       if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
+               bpf_error("malformed decnet address '%s'", s);
+
+       addr = (area << AREASHIFT) & AREAMASK;
+       addr |= (node & NODEMASK);
+
+       return(addr);
+}
+
+/*
+ * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
+ * ethernet address.  Assumes 's' is well formed.
+ */
+u_char *
+pcap_ether_aton(const char *s)
+{
+       register u_char *ep, *e;
+       register u_int d;
+
+       e = ep = (u_char *)malloc(6);
+
+       while (*s) {
+               if (*s == ':')
+                       s += 1;
+               d = xdtoi(*s++);
+               if (isxdigit(*s)) {
+                       d <<= 4;
+                       d |= xdtoi(*s++);
+               }
+               *ep++ = d;
+       }
+
+       return (e);
+}
+
+#ifndef HAVE_ETHER_HOSTTON
+/* Roll our own */
+u_char *
+pcap_ether_hostton(const char *name)
+{
+       register struct pcap_etherent *ep;
+       register u_char *ap;
+       static FILE *fp = NULL;
+       static init = 0;
+
+       if (!init) {
+               fp = fopen(PCAP_ETHERS_FILE, "r");
+               ++init;
+               if (fp == NULL)
+                       return (NULL);
+       } else if (fp == NULL)
+               return (NULL);
+       else
+               rewind(fp);
+       
+       while ((ep = pcap_next_etherent(fp)) != NULL) {
+               if (strcmp(ep->name, name) == 0) {
+                       ap = (u_char *)malloc(6);
+                       if (ap != NULL) {
+                               memcpy(ap, ep->addr, 6);
+                               return (ap);
+                       }
+                       break;
+               }
+       }
+       return (NULL);
+}
+#else
+
+#ifndef sgi
+extern int ether_hostton(char *, struct ether_addr *);
+#endif
+
+/* Use the os supplied routines */
+u_char *
+pcap_ether_hostton(const char *name)
+{
+       register u_char *ap;
+       u_char a[6];
+
+       ap = NULL;
+       if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) {
+               ap = (u_char *)malloc(6);
+               if (ap != NULL)
+                       memcpy(ap, a, 6);
+       }
+       return (ap);
+}
+#endif
+
+u_short
+__pcap_nametodnaddr(const char *name)
+{
+#ifdef DECNETLIB
+       struct nodeent *getnodebyname();
+       struct nodeent *nep;
+       unsigned short res;
+
+       nep = getnodebyname(name);
+       if (nep == ((struct nodeent *)0))
+               bpf_error("unknown decnet host name '%s'\n", name);
+
+       memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
+       return(res);
+#else
+       bpf_error("decnet name support not included, '%s' cannot be translated\n",
+               name);
+#ifdef lint
+       return 0;
+#endif
+#endif
+}
diff --git a/pcap/optimize.c b/pcap/optimize.c
new file mode 100644 (file)
index 0000000..e78ce1c
--- /dev/null
@@ -0,0 +1,2029 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: optimize.c,v 1.5 1996/09/16 02:33:07 tholo Exp $      */
+
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Optimization module for tcpdump intermediate representation.
+ */
+#ifndef lint
+static char rcsid[] =
+    "@(#) Header: optimize.c,v 1.58 96/06/16 22:36:59 leres Exp (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <net/bpf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+#include "gencode.h"
+
+#ifdef BDEBUG
+extern int dflag;
+#endif
+
+#define A_ATOM BPF_MEMWORDS
+#define X_ATOM (BPF_MEMWORDS+1)
+
+#define NOP -1
+
+/*
+ * This define is used to represent *both* the accumulator and
+ * x register in use-def computations.
+ * Currently, the use-def code assumes only one definition per instruction.
+ */
+#define AX_ATOM N_ATOMS
+
+/*
+ * A flag to indicate that further optimization is needed.
+ * Iterative passes are continued until a given pass yields no
+ * branch movement.
+ */
+static int done;
+
+/*
+ * A block is marked if only if its mark equals the current mark.
+ * Rather than traverse the code array, marking each item, 'cur_mark' is
+ * incremented.  This automatically makes each element unmarked.
+ */
+static int cur_mark;
+#define isMarked(p) ((p)->mark == cur_mark)
+#define unMarkAll() cur_mark += 1
+#define Mark(p) ((p)->mark = cur_mark)
+
+static void opt_init(struct block *);
+static void opt_cleanup(void);
+
+static void make_marks(struct block *);
+static void mark_code(struct block *);
+
+static void intern_blocks(struct block *);
+
+static int eq_slist(struct slist *, struct slist *);
+
+static void find_levels_r(struct block *);
+
+static void find_levels(struct block *);
+static void find_dom(struct block *);
+static void propedom(struct edge *);
+static void find_edom(struct block *);
+static void find_closure(struct block *);
+static int atomuse(struct stmt *);
+static int atomdef(struct stmt *);
+static void compute_local_ud(struct block *);
+static void find_ud(struct block *);
+static void init_val(void);
+static int F(int, int, int);
+static __inline void vstore(struct stmt *, int *, int, int);
+static void opt_blk(struct block *, int);
+static int use_conflict(struct block *, struct block *);
+static void opt_j(struct edge *);
+static void or_pullup(struct block *);
+static void and_pullup(struct block *);
+static void opt_blks(struct block *, int);
+static __inline void link_inedge(struct edge *, struct block *);
+static void find_inedges(struct block *);
+static void opt_root(struct block **);
+static void opt_loop(struct block *, int);
+static void fold_op(struct stmt *, int, int);
+static __inline struct slist *this_op(struct slist *);
+static void opt_not(struct block *);
+static void opt_peep(struct block *);
+static void opt_stmt(struct stmt *, int[], int);
+static void deadstmt(struct stmt *, struct stmt *[]);
+static void opt_deadstores(struct block *);
+static void opt_blk(struct block *, int);
+static int use_conflict(struct block *, struct block *);
+static void opt_j(struct edge *);
+static struct block *fold_edge(struct block *, struct edge *);
+static __inline int eq_blk(struct block *, struct block *);
+static int slength(struct slist *);
+static int count_blocks(struct block *);
+static void number_blks_r(struct block *);
+static int count_stmts(struct block *);
+static int convert_code_r(struct block *);
+#ifdef BDEBUG
+static void opt_dump(struct block *);
+#endif
+
+static int n_blocks;
+struct block **blocks;
+static int n_edges;
+struct edge **edges;
+
+/*
+ * A bit vector set representation of the dominators.
+ * We round up the set size to the next power of two.
+ */
+static int nodewords;
+static int edgewords;
+struct block **levels;
+bpf_u_int32 *space;
+#define BITS_PER_WORD (8*sizeof(bpf_u_int32))
+/*
+ * True if a is in uset {p}
+ */
+#define SET_MEMBER(p, a) \
+((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))
+
+/*
+ * Add 'a' to uset p.
+ */
+#define SET_INSERT(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * Delete 'a' from uset p.
+ */
+#define SET_DELETE(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * a := a intersect b
+ */
+#define SET_INTERSECT(a, b, n)\
+{\
+       register bpf_u_int32 *_x = a, *_y = b;\
+       register int _n = n;\
+       while (--_n >= 0) *_x++ &= *_y++;\
+}
+
+/*
+ * a := a - b
+ */
+#define SET_SUBTRACT(a, b, n)\
+{\
+       register bpf_u_int32 *_x = a, *_y = b;\
+       register int _n = n;\
+       while (--_n >= 0) *_x++ &=~ *_y++;\
+}
+
+/*
+ * a := a union b
+ */
+#define SET_UNION(a, b, n)\
+{\
+       register bpf_u_int32 *_x = a, *_y = b;\
+       register int _n = n;\
+       while (--_n >= 0) *_x++ |= *_y++;\
+}
+
+static uset all_dom_sets;
+static uset all_closure_sets;
+static uset all_edge_sets;
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+static void
+find_levels_r(b)
+       struct block *b;
+{
+       int level;
+
+       if (isMarked(b))
+               return;
+
+       Mark(b);
+       b->link = 0;
+
+       if (JT(b)) {
+               find_levels_r(JT(b));
+               find_levels_r(JF(b));
+               level = MAX(JT(b)->level, JF(b)->level) + 1;
+       } else
+               level = 0;
+       b->level = level;
+       b->link = levels[level];
+       levels[level] = b;
+}
+
+/*
+ * Level graph.  The levels go from 0 at the leaves to
+ * N_LEVELS at the root.  The levels[] array points to the
+ * first node of the level list, whose elements are linked
+ * with the 'link' field of the struct block.
+ */
+static void
+find_levels(root)
+       struct block *root;
+{
+       memset((char *)levels, 0, n_blocks * sizeof(*levels));
+       unMarkAll();
+       find_levels_r(root);
+}
+
+/*
+ * Find dominator relationships.
+ * Assumes graph has been leveled.
+ */
+static void
+find_dom(root)
+       struct block *root;
+{
+       int i;
+       struct block *b;
+       bpf_u_int32 *x;
+
+       /*
+        * Initialize sets to contain all nodes.
+        */
+       x = all_dom_sets;
+       i = n_blocks * nodewords;
+       while (--i >= 0)
+               *x++ = ~0;
+       /* Root starts off empty. */
+       for (i = nodewords; --i >= 0;)
+               root->dom[i] = 0;
+
+       /* root->level is the highest level no found. */
+       for (i = root->level; i >= 0; --i) {
+               for (b = levels[i]; b; b = b->link) {
+                       SET_INSERT(b->dom, b->id);
+                       if (JT(b) == 0)
+                               continue;
+                       SET_INTERSECT(JT(b)->dom, b->dom, nodewords);
+                       SET_INTERSECT(JF(b)->dom, b->dom, nodewords);
+               }
+       }
+}
+
+static void
+propedom(ep)
+       struct edge *ep;
+{
+       SET_INSERT(ep->edom, ep->id);
+       if (ep->succ) {
+               SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords);
+               SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords);
+       }
+}
+
+/*
+ * Compute edge dominators.
+ * Assumes graph has been leveled and predecessors established.
+ */
+static void
+find_edom(root)
+       struct block *root;
+{
+       int i;
+       uset x;
+       struct block *b;
+
+       x = all_edge_sets;
+       for (i = n_edges * edgewords; --i >= 0; )
+               x[i] = ~0;
+
+       /* root->level is the highest level no found. */
+       memset(root->et.edom, 0, edgewords * sizeof(*(uset)0));
+       memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0));
+       for (i = root->level; i >= 0; --i) {
+               for (b = levels[i]; b != 0; b = b->link) {
+                       propedom(&b->et);
+                       propedom(&b->ef);
+               }
+       }
+}
+
+/*
+ * Find the backwards transitive closure of the flow graph.  These sets
+ * are backwards in the sense that we find the set of nodes that reach
+ * a given node, not the set of nodes that can be reached by a node.
+ *
+ * Assumes graph has been leveled.
+ */
+static void
+find_closure(root)
+       struct block *root;
+{
+       int i;
+       struct block *b;
+
+       /*
+        * Initialize sets to contain no nodes.
+        */
+       memset((char *)all_closure_sets, 0,
+             n_blocks * nodewords * sizeof(*all_closure_sets));
+
+       /* root->level is the highest level no found. */
+       for (i = root->level; i >= 0; --i) {
+               for (b = levels[i]; b; b = b->link) {
+                       SET_INSERT(b->closure, b->id);
+                       if (JT(b) == 0)
+                               continue;
+                       SET_UNION(JT(b)->closure, b->closure, nodewords);
+                       SET_UNION(JF(b)->closure, b->closure, nodewords);
+               }
+       }
+}
+
+/*
+ * Return the register number that is used by s.  If A and X are both
+ * used, return AX_ATOM.  If no register is used, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomuse(s)
+       struct stmt *s;
+{
+       register int c = s->code;
+
+       if (c == NOP)
+               return -1;
+
+       switch (BPF_CLASS(c)) {
+
+       case BPF_RET:
+               return (BPF_RVAL(c) == BPF_A) ? A_ATOM :
+                       (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1;
+
+       case BPF_LD:
+       case BPF_LDX:
+               return (BPF_MODE(c) == BPF_IND) ? X_ATOM :
+                       (BPF_MODE(c) == BPF_MEM) ? s->k : -1;
+
+       case BPF_ST:
+               return A_ATOM;
+
+       case BPF_STX:
+               return X_ATOM;
+
+       case BPF_JMP:
+       case BPF_ALU:
+               if (BPF_SRC(c) == BPF_X)
+                       return AX_ATOM;
+               return A_ATOM;
+
+       case BPF_MISC:
+               return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM;
+       }
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * Return the register number that is defined by 's'.  We assume that
+ * a single stmt cannot define more than one register.  If no register
+ * is defined, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomdef(s)
+       struct stmt *s;
+{
+       if (s->code == NOP)
+               return -1;
+
+       switch (BPF_CLASS(s->code)) {
+
+       case BPF_LD:
+       case BPF_ALU:
+               return A_ATOM;
+
+       case BPF_LDX:
+               return X_ATOM;
+
+       case BPF_ST:
+       case BPF_STX:
+               return s->k;
+
+       case BPF_MISC:
+               return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM;
+       }
+       return -1;
+}
+
+static void
+compute_local_ud(b)
+       struct block *b;
+{
+       struct slist *s;
+       atomset def = 0, use = 0, kill = 0;
+       int atom;
+
+       for (s = b->stmts; s; s = s->next) {
+               if (s->s.code == NOP)
+                       continue;
+               atom = atomuse(&s->s);
+               if (atom >= 0) {
+                       if (atom == AX_ATOM) {
+                               if (!ATOMELEM(def, X_ATOM))
+                                       use |= ATOMMASK(X_ATOM);
+                               if (!ATOMELEM(def, A_ATOM))
+                                       use |= ATOMMASK(A_ATOM);
+                       }
+                       else if (atom < N_ATOMS) {
+                               if (!ATOMELEM(def, atom))
+                                       use |= ATOMMASK(atom);
+                       }
+                       else
+                               abort();
+               }
+               atom = atomdef(&s->s);
+               if (atom >= 0) {
+                       if (!ATOMELEM(use, atom))
+                               kill |= ATOMMASK(atom);
+                       def |= ATOMMASK(atom);
+               }
+       }
+       if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP)
+               use |= ATOMMASK(A_ATOM);
+
+       b->def = def;
+       b->kill = kill;
+       b->in_use = use;
+}
+
+/*
+ * Assume graph is already leveled.
+ */
+static void
+find_ud(root)
+       struct block *root;
+{
+       int i, maxlevel;
+       struct block *p;
+
+       /*
+        * root->level is the highest level no found;
+        * count down from there.
+        */
+       maxlevel = root->level;
+       for (i = maxlevel; i >= 0; --i)
+               for (p = levels[i]; p; p = p->link) {
+                       compute_local_ud(p);
+                       p->out_use = 0;
+               }
+
+       for (i = 1; i <= maxlevel; ++i) {
+               for (p = levels[i]; p; p = p->link) {
+                       p->out_use |= JT(p)->in_use | JF(p)->in_use;
+                       p->in_use |= p->out_use &~ p->kill;
+               }
+       }
+}
+
+/*
+ * These data structures are used in a Cocke and Shwarz style
+ * value numbering scheme.  Since the flowgraph is acyclic,
+ * exit values can be propagated from a node's predecessors
+ * provided it is uniquely defined.
+ */
+struct valnode {
+       int code;
+       int v0, v1;
+       int val;
+       struct valnode *next;
+};
+
+#define MODULUS 213
+static struct valnode *hashtbl[MODULUS];
+static int curval;
+static int maxval;
+
+/* Integer constants mapped with the load immediate opcode. */
+#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L)
+
+struct vmapinfo {
+       int is_const;
+       bpf_int32 const_val;
+};
+
+struct vmapinfo *vmap;
+struct valnode *vnode_base;
+struct valnode *next_vnode;
+
+static void
+init_val()
+{
+       curval = 0;
+       next_vnode = vnode_base;
+       memset((char *)vmap, 0, maxval * sizeof(*vmap));
+       memset((char *)hashtbl, 0, sizeof hashtbl);
+}
+
+/* Because we really don't have an IR, this stuff is a little messy. */
+static int
+F(code, v0, v1)
+       int code;
+       int v0, v1;
+{
+       u_int hash;
+       int val;
+       struct valnode *p;
+
+       hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
+       hash %= MODULUS;
+
+       for (p = hashtbl[hash]; p; p = p->next)
+               if (p->code == code && p->v0 == v0 && p->v1 == v1)
+                       return p->val;
+
+       val = ++curval;
+       if (BPF_MODE(code) == BPF_IMM &&
+           (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
+               vmap[val].const_val = v0;
+               vmap[val].is_const = 1;
+       }
+       p = next_vnode++;
+       p->val = val;
+       p->code = code;
+       p->v0 = v0;
+       p->v1 = v1;
+       p->next = hashtbl[hash];
+       hashtbl[hash] = p;
+
+       return val;
+}
+
+static __inline void
+vstore(s, valp, newval, alter)
+       struct stmt *s;
+       int *valp;
+       int newval;
+       int alter;
+{
+       if (alter && *valp == newval)
+               s->code = NOP;
+       else
+               *valp = newval;
+}
+
+static void
+fold_op(s, v0, v1)
+       struct stmt *s;
+       int v0, v1;
+{
+       bpf_int32 a, b;
+
+       a = vmap[v0].const_val;
+       b = vmap[v1].const_val;
+
+       switch (BPF_OP(s->code)) {
+       case BPF_ADD:
+               a += b;
+               break;
+
+       case BPF_SUB:
+               a -= b;
+               break;
+
+       case BPF_MUL:
+               a *= b;
+               break;
+
+       case BPF_DIV:
+               if (b == 0)
+                       bpf_error("division by zero");
+               a /= b;
+               break;
+
+       case BPF_AND:
+               a &= b;
+               break;
+
+       case BPF_OR:
+               a |= b;
+               break;
+
+       case BPF_LSH:
+               a <<= b;
+               break;
+
+       case BPF_RSH:
+               a >>= b;
+               break;
+
+       case BPF_NEG:
+               a = -a;
+               break;
+
+       default:
+               abort();
+       }
+       s->k = a;
+       s->code = BPF_LD|BPF_IMM;
+       done = 0;
+}
+
+static __inline struct slist *
+this_op(s)
+       struct slist *s;
+{
+       while (s != 0 && s->s.code == NOP)
+               s = s->next;
+       return s;
+}
+
+static void
+opt_not(b)
+       struct block *b;
+{
+       struct block *tmp = JT(b);
+
+       JT(b) = JF(b);
+       JF(b) = tmp;
+}
+
+static void
+opt_peep(b)
+       struct block *b;
+{
+       struct slist *s;
+       struct slist *next, *last;
+       int val;
+
+       s = b->stmts;
+       if (s == 0)
+               return;
+
+       last = s;
+       while (1) {
+               s = this_op(s);
+               if (s == 0)
+                       break;
+               next = this_op(s->next);
+               if (next == 0)
+                       break;
+               last = next;
+
+               /*
+                * st  M[k]     -->     st  M[k]
+                * ldx M[k]             tax
+                */
+               if (s->s.code == BPF_ST &&
+                   next->s.code == (BPF_LDX|BPF_MEM) &&
+                   s->s.k == next->s.k) {
+                       done = 0;
+                       next->s.code = BPF_MISC|BPF_TAX;
+               }
+               /*
+                * ld  #k       -->     ldx  #k
+                * tax                  txa
+                */
+               if (s->s.code == (BPF_LD|BPF_IMM) &&
+                   next->s.code == (BPF_MISC|BPF_TAX)) {
+                       s->s.code = BPF_LDX|BPF_IMM;
+                       next->s.code = BPF_MISC|BPF_TXA;
+                       done = 0;
+               }
+               /*
+                * This is an ugly special case, but it happens
+                * when you say tcp[k] or udp[k] where k is a constant.
+                */
+               if (s->s.code == (BPF_LD|BPF_IMM)) {
+                       struct slist *add, *tax, *ild;
+
+                       /*
+                        * Check that X isn't used on exit from this
+                        * block (which the optimizer might cause).
+                        * We know the code generator won't generate
+                        * any local dependencies.
+                        */
+                       if (ATOMELEM(b->out_use, X_ATOM))
+                               break;
+
+                       if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
+                               add = next;
+                       else
+                               add = this_op(next->next);
+                       if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X))
+                               break;
+
+                       tax = this_op(add->next);
+                       if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
+                               break;
+
+                       ild = this_op(tax->next);
+                       if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
+                           BPF_MODE(ild->s.code) != BPF_IND)
+                               break;
+                       /*
+                        * XXX We need to check that X is not
+                        * subsequently used.  We know we can eliminate the
+                        * accumulator modifications since it is defined
+                        * by the last stmt of this sequence.
+                        *
+                        * We want to turn this sequence:
+                        *
+                        * (004) ldi     #0x2           {s}
+                        * (005) ldxms   [14]           {next}  -- optional
+                        * (006) addx                   {add}
+                        * (007) tax                    {tax}
+                        * (008) ild     [x+0]          {ild}
+                        *
+                        * into this sequence:
+                        *
+                        * (004) nop
+                        * (005) ldxms   [14]
+                        * (006) nop
+                        * (007) nop
+                        * (008) ild     [x+2]
+                        *
+                        */
+                       ild->s.k += s->s.k;
+                       s->s.code = NOP;
+                       add->s.code = NOP;
+                       tax->s.code = NOP;
+                       done = 0;
+               }
+               s = next;
+       }
+       /*
+        * If we have a subtract to do a comparison, and the X register
+        * is a known constant, we can merge this value into the
+        * comparison.
+        */
+       if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) &&
+           !ATOMELEM(b->out_use, A_ATOM)) {
+               val = b->val[X_ATOM];
+               if (vmap[val].is_const) {
+                       int op;
+
+                       b->s.k += vmap[val].const_val;
+                       op = BPF_OP(b->s.code);
+                       if (op == BPF_JGT || op == BPF_JGE) {
+                               struct block *t = JT(b);
+                               JT(b) = JF(b);
+                               JF(b) = t;
+                               b->s.k += 0x80000000;
+                       }
+                       last->s.code = NOP;
+                       done = 0;
+               } else if (b->s.k == 0) {
+                       /*
+                        * sub x  ->    nop
+                        * j  #0        j  x
+                        */
+                       last->s.code = NOP;
+                       b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) |
+                               BPF_X;
+                       done = 0;
+               }
+       }
+       /*
+        * Likewise, a constant subtract can be simplified.
+        */
+       else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) &&
+                !ATOMELEM(b->out_use, A_ATOM)) {
+               int op;
+
+               b->s.k += last->s.k;
+               last->s.code = NOP;
+               op = BPF_OP(b->s.code);
+               if (op == BPF_JGT || op == BPF_JGE) {
+                       struct block *t = JT(b);
+                       JT(b) = JF(b);
+                       JF(b) = t;
+                       b->s.k += 0x80000000;
+               }
+               done = 0;
+       }
+       /*
+        * and #k       nop
+        * jeq #0  ->   jset #k
+        */
+       if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
+           !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) {
+               b->s.k = last->s.k;
+               b->s.code = BPF_JMP|BPF_K|BPF_JSET;
+               last->s.code = NOP;
+               done = 0;
+               opt_not(b);
+       }
+       /*
+        * If the accumulator is a known constant, we can compute the
+        * comparison result.
+        */
+       val = b->val[A_ATOM];
+       if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
+               bpf_int32 v = vmap[val].const_val;
+               switch (BPF_OP(b->s.code)) {
+
+               case BPF_JEQ:
+                       v = v == b->s.k;
+                       break;
+
+               case BPF_JGT:
+                       v = (unsigned)v > b->s.k;
+                       break;
+
+               case BPF_JGE:
+                       v = (unsigned)v >= b->s.k;
+                       break;
+
+               case BPF_JSET:
+                       v &= b->s.k;
+                       break;
+
+               default:
+                       abort();
+               }
+               if (JF(b) != JT(b))
+                       done = 0;
+               if (v)
+                       JF(b) = JT(b);
+               else
+                       JT(b) = JF(b);
+       }
+}
+
+/*
+ * Compute the symbolic value of expression of 's', and update
+ * anything it defines in the value table 'val'.  If 'alter' is true,
+ * do various optimizations.  This code would be cleaner if symbolic
+ * evaluation and code transformations weren't folded together.
+ */
+static void
+opt_stmt(s, val, alter)
+       struct stmt *s;
+       int val[];
+       int alter;
+{
+       int op;
+       int v;
+
+       switch (s->code) {
+
+       case BPF_LD|BPF_ABS|BPF_W:
+       case BPF_LD|BPF_ABS|BPF_H:
+       case BPF_LD|BPF_ABS|BPF_B:
+               v = F(s->code, s->k, 0L);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LD|BPF_IND|BPF_W:
+       case BPF_LD|BPF_IND|BPF_H:
+       case BPF_LD|BPF_IND|BPF_B:
+               v = val[X_ATOM];
+               if (alter && vmap[v].is_const) {
+                       s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
+                       s->k += vmap[v].const_val;
+                       v = F(s->code, s->k, 0L);
+                       done = 0;
+               }
+               else
+                       v = F(s->code, s->k, v);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LD|BPF_LEN:
+               v = F(s->code, 0L, 0L);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LD|BPF_IMM:
+               v = K(s->k);
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_LDX|BPF_IMM:
+               v = K(s->k);
+               vstore(s, &val[X_ATOM], v, alter);
+               break;
+
+       case BPF_LDX|BPF_MSH|BPF_B:
+               v = F(s->code, s->k, 0L);
+               vstore(s, &val[X_ATOM], v, alter);
+               break;
+
+       case BPF_ALU|BPF_NEG:
+               if (alter && vmap[val[A_ATOM]].is_const) {
+                       s->code = BPF_LD|BPF_IMM;
+                       s->k = -vmap[val[A_ATOM]].const_val;
+                       val[A_ATOM] = K(s->k);
+               }
+               else
+                       val[A_ATOM] = F(s->code, val[A_ATOM], 0L);
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_K:
+       case BPF_ALU|BPF_SUB|BPF_K:
+       case BPF_ALU|BPF_MUL|BPF_K:
+       case BPF_ALU|BPF_DIV|BPF_K:
+       case BPF_ALU|BPF_AND|BPF_K:
+       case BPF_ALU|BPF_OR|BPF_K:
+       case BPF_ALU|BPF_LSH|BPF_K:
+       case BPF_ALU|BPF_RSH|BPF_K:
+               op = BPF_OP(s->code);
+               if (alter) {
+                       if (s->k == 0) {
+                               if (op == BPF_ADD || op == BPF_SUB ||
+                                   op == BPF_LSH || op == BPF_RSH ||
+                                   op == BPF_OR) {
+                                       s->code = NOP;
+                                       break;
+                               }
+                               if (op == BPF_MUL || op == BPF_AND) {
+                                       s->code = BPF_LD|BPF_IMM;
+                                       val[A_ATOM] = K(s->k);
+                                       break;
+                               }
+                       }
+                       if (vmap[val[A_ATOM]].is_const) {
+                               fold_op(s, val[A_ATOM], K(s->k));
+                               val[A_ATOM] = K(s->k);
+                               break;
+                       }
+               }
+               val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k));
+               break;
+
+       case BPF_ALU|BPF_ADD|BPF_X:
+       case BPF_ALU|BPF_SUB|BPF_X:
+       case BPF_ALU|BPF_MUL|BPF_X:
+       case BPF_ALU|BPF_DIV|BPF_X:
+       case BPF_ALU|BPF_AND|BPF_X:
+       case BPF_ALU|BPF_OR|BPF_X:
+       case BPF_ALU|BPF_LSH|BPF_X:
+       case BPF_ALU|BPF_RSH|BPF_X:
+               op = BPF_OP(s->code);
+               if (alter && vmap[val[X_ATOM]].is_const) {
+                       if (vmap[val[A_ATOM]].is_const) {
+                               fold_op(s, val[A_ATOM], val[X_ATOM]);
+                               val[A_ATOM] = K(s->k);
+                       }
+                       else {
+                               s->code = BPF_ALU|BPF_K|op;
+                               s->k = vmap[val[X_ATOM]].const_val;
+                               done = 0;
+                               val[A_ATOM] =
+                                       F(s->code, val[A_ATOM], K(s->k));
+                       }
+                       break;
+               }
+               /*
+                * Check if we're doing something to an accumulator
+                * that is 0, and simplify.  This may not seem like
+                * much of a simplification but it could open up further
+                * optimizations.
+                * XXX We could also check for mul by 1, and -1, etc.
+                */
+               if (alter && vmap[val[A_ATOM]].is_const
+                   && vmap[val[A_ATOM]].const_val == 0) {
+                       if (op == BPF_ADD || op == BPF_OR ||
+                           op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) {
+                               s->code = BPF_MISC|BPF_TXA;
+                               vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+                               break;
+                       }
+                       else if (op == BPF_MUL || op == BPF_DIV ||
+                                op == BPF_AND) {
+                               s->code = BPF_LD|BPF_IMM;
+                               s->k = 0;
+                               vstore(s, &val[A_ATOM], K(s->k), alter);
+                               break;
+                       }
+                       else if (op == BPF_NEG) {
+                               s->code = NOP;
+                               break;
+                       }
+               }
+               val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]);
+               break;
+
+       case BPF_MISC|BPF_TXA:
+               vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+               break;
+
+       case BPF_LD|BPF_MEM:
+               v = val[s->k];
+               if (alter && vmap[v].is_const) {
+                       s->code = BPF_LD|BPF_IMM;
+                       s->k = vmap[v].const_val;
+                       done = 0;
+               }
+               vstore(s, &val[A_ATOM], v, alter);
+               break;
+
+       case BPF_MISC|BPF_TAX:
+               vstore(s, &val[X_ATOM], val[A_ATOM], alter);
+               break;
+
+       case BPF_LDX|BPF_MEM:
+               v = val[s->k];
+               if (alter && vmap[v].is_const) {
+                       s->code = BPF_LDX|BPF_IMM;
+                       s->k = vmap[v].const_val;
+                       done = 0;
+               }
+               vstore(s, &val[X_ATOM], v, alter);
+               break;
+
+       case BPF_ST:
+               vstore(s, &val[s->k], val[A_ATOM], alter);
+               break;
+
+       case BPF_STX:
+               vstore(s, &val[s->k], val[X_ATOM], alter);
+               break;
+       }
+}
+
+static void
+deadstmt(s, last)
+       register struct stmt *s;
+       register struct stmt *last[];
+{
+       register int atom;
+
+       atom = atomuse(s);
+       if (atom >= 0) {
+               if (atom == AX_ATOM) {
+                       last[X_ATOM] = 0;
+                       last[A_ATOM] = 0;
+               }
+               else
+                       last[atom] = 0;
+       }
+       atom = atomdef(s);
+       if (atom >= 0) {
+               if (last[atom]) {
+                       done = 0;
+                       last[atom]->code = NOP;
+               }
+               last[atom] = s;
+       }
+}
+
+static void
+opt_deadstores(b)
+       register struct block *b;
+{
+       register struct slist *s;
+       register int atom;
+       struct stmt *last[N_ATOMS];
+
+       memset((char *)last, 0, sizeof last);
+
+       for (s = b->stmts; s != 0; s = s->next)
+               deadstmt(&s->s, last);
+       deadstmt(&b->s, last);
+
+       for (atom = 0; atom < N_ATOMS; ++atom)
+               if (last[atom] && !ATOMELEM(b->out_use, atom)) {
+                       last[atom]->code = NOP;
+                       done = 0;
+               }
+}
+
+static void
+opt_blk(b, do_stmts)
+       struct block *b;
+       int do_stmts;
+{
+       struct slist *s;
+       struct edge *p;
+       int i;
+       bpf_int32 aval;
+
+       /*
+        * Initialize the atom values.
+        * If we have no predecessors, everything is undefined.
+        * Otherwise, we inherent our values from our predecessors.
+        * If any register has an ambiguous value (i.e. control paths are
+        * merging) give it the undefined value of 0.
+        */
+       p = b->in_edges;
+       if (p == 0)
+               memset((char *)b->val, 0, sizeof(b->val));
+       else {
+               memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));
+               while ((p = p->next) != NULL) {
+                       for (i = 0; i < N_ATOMS; ++i)
+                               if (b->val[i] != p->pred->val[i])
+                                       b->val[i] = 0;
+               }
+       }
+       aval = b->val[A_ATOM];
+       for (s = b->stmts; s; s = s->next)
+               opt_stmt(&s->s, b->val, do_stmts);
+
+       /*
+        * This is a special case: if we don't use anything from this
+        * block, and we load the accumulator with value that is
+        * already there, or if this block is a return,
+        * eliminate all the statements.
+        */
+       if (do_stmts && 
+           ((b->out_use == 0 && aval != 0 &&b->val[A_ATOM] == aval) ||
+            BPF_CLASS(b->s.code) == BPF_RET)) {
+               if (b->stmts != 0) {
+                       b->stmts = 0;
+                       done = 0;
+               }
+       } else {
+               opt_peep(b);
+               opt_deadstores(b);
+       }
+       /*
+        * Set up values for branch optimizer.
+        */
+       if (BPF_SRC(b->s.code) == BPF_K)
+               b->oval = K(b->s.k);
+       else
+               b->oval = b->val[X_ATOM];
+       b->et.code = b->s.code;
+       b->ef.code = -b->s.code;
+}
+
+/*
+ * Return true if any register that is used on exit from 'succ', has
+ * an exit value that is different from the corresponding exit value
+ * from 'b'.
+ */
+static int
+use_conflict(b, succ)
+       struct block *b, *succ;
+{
+       int atom;
+       atomset use = succ->out_use;
+
+       if (use == 0)
+               return 0;
+
+       for (atom = 0; atom < N_ATOMS; ++atom)
+               if (ATOMELEM(use, atom))
+                       if (b->val[atom] != succ->val[atom])
+                               return 1;
+       return 0;
+}
+
+static struct block *
+fold_edge(child, ep)
+       struct block *child;
+       struct edge *ep;
+{
+       int sense;
+       int aval0, aval1, oval0, oval1;
+       int code = ep->code;
+
+       if (code < 0) {
+               code = -code;
+               sense = 0;
+       } else
+               sense = 1;
+
+       if (child->s.code != code)
+               return 0;
+
+       aval0 = child->val[A_ATOM];
+       oval0 = child->oval;
+       aval1 = ep->pred->val[A_ATOM];
+       oval1 = ep->pred->oval;
+
+       if (aval0 != aval1)
+               return 0;
+
+       if (oval0 == oval1)
+               /*
+                * The operands are identical, so the
+                * result is true if a true branch was
+                * taken to get here, otherwise false.
+                */
+               return sense ? JT(child) : JF(child);
+
+       if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K))
+               /*
+                * At this point, we only know the comparison if we
+                * came down the true branch, and it was an equality
+                * comparison with a constant.  We rely on the fact that
+                * distinct constants have distinct value numbers.
+                */
+               return JF(child);
+
+       return 0;
+}
+
+static void
+opt_j(ep)
+       struct edge *ep;
+{
+       register int i, k;
+       register struct block *target;
+
+       if (JT(ep->succ) == 0)
+               return;
+
+       if (JT(ep->succ) == JF(ep->succ)) {
+               /*
+                * Common branch targets can be eliminated, provided
+                * there is no data dependency.
+                */
+               if (!use_conflict(ep->pred, ep->succ->et.succ)) {
+                       done = 0;
+                       ep->succ = JT(ep->succ);
+               }
+       }
+       /*
+        * For each edge dominator that matches the successor of this
+        * edge, promote the edge successor to the its grandchild.
+        *
+        * XXX We violate the set abstraction here in favor a reasonably
+        * efficient loop.
+        */
+ top:
+       for (i = 0; i < edgewords; ++i) {
+               register bpf_u_int32 x = ep->edom[i];
+
+               while (x != 0) {
+                       k = ffs(x) - 1;
+                       x &=~ (1 << k);
+                       k += i * BITS_PER_WORD;
+
+                       target = fold_edge(ep->succ, edges[k]);
+                       /*
+                        * Check that there is no data dependency between
+                        * nodes that will be violated if we move the edge.
+                        */
+                       if (target != 0 && !use_conflict(ep->pred, target)) {
+                               done = 0;
+                               ep->succ = target;
+                               if (JT(target) != 0)
+                                       /*
+                                        * Start over unless we hit a leaf.
+                                        */
+                                       goto top;
+                               return;
+                       }
+               }
+       }
+}
+
+
+static void
+or_pullup(b)
+       struct block *b;
+{
+       int val, at_top;
+       struct block *pull;
+       struct block **diffp, **samep;
+       struct edge *ep;
+
+       ep = b->in_edges;
+       if (ep == 0)
+               return;
+
+       /*
+        * Make sure each predecessor loads the same value.
+        * XXX why?
+        */
+       val = ep->pred->val[A_ATOM];
+       for (ep = ep->next; ep != 0; ep = ep->next)
+               if (val != ep->pred->val[A_ATOM])
+                       return;
+
+       if (JT(b->in_edges->pred) == b)
+               diffp = &JT(b->in_edges->pred);
+       else
+               diffp = &JF(b->in_edges->pred);
+
+       at_top = 1;
+       while (1) {
+               if (*diffp == 0)
+                       return;
+
+               if (JT(*diffp) != JT(b))
+                       return;
+
+               if (!SET_MEMBER((*diffp)->dom, b->id))
+                       return;
+
+               if ((*diffp)->val[A_ATOM] != val)
+                       break;
+
+               diffp = &JF(*diffp);
+               at_top = 0;
+       }
+       samep = &JF(*diffp);
+       while (1) {
+               if (*samep == 0)
+                       return;
+
+               if (JT(*samep) != JT(b))
+                       return;
+
+               if (!SET_MEMBER((*samep)->dom, b->id))
+                       return;
+
+               if ((*samep)->val[A_ATOM] == val)
+                       break;
+
+               /* XXX Need to check that there are no data dependencies
+                  between dp0 and dp1.  Currently, the code generator
+                  will not produce such dependencies. */
+               samep = &JF(*samep);
+       }
+#ifdef notdef
+       /* XXX This doesn't cover everything. */
+       for (i = 0; i < N_ATOMS; ++i)
+               if ((*samep)->val[i] != pred->val[i])
+                       return;
+#endif
+       /* Pull up the node. */
+       pull = *samep;
+       *samep = JF(pull);
+       JF(pull) = *diffp;
+
+       /*
+        * At the top of the chain, each predecessor needs to point at the
+        * pulled up node.  Inside the chain, there is only one predecessor
+        * to worry about.
+        */
+       if (at_top) {
+               for (ep = b->in_edges; ep != 0; ep = ep->next) {
+                       if (JT(ep->pred) == b)
+                               JT(ep->pred) = pull;
+                       else
+                               JF(ep->pred) = pull;
+               }
+       }
+       else
+               *diffp = pull;
+
+       done = 0;
+}
+
+static void
+and_pullup(b)
+       struct block *b;
+{
+       int val, at_top;
+       struct block *pull;
+       struct block **diffp, **samep;
+       struct edge *ep;
+
+       ep = b->in_edges;
+       if (ep == 0)
+               return;
+
+       /*
+        * Make sure each predecessor loads the same value.
+        */
+       val = ep->pred->val[A_ATOM];
+       for (ep = ep->next; ep != 0; ep = ep->next)
+               if (val != ep->pred->val[A_ATOM])
+                       return;
+
+       if (JT(b->in_edges->pred) == b)
+               diffp = &JT(b->in_edges->pred);
+       else
+               diffp = &JF(b->in_edges->pred);
+
+       at_top = 1;
+       while (1) {
+               if (*diffp == 0)
+                       return;
+
+               if (JF(*diffp) != JF(b))
+                       return;
+
+               if (!SET_MEMBER((*diffp)->dom, b->id))
+                       return;
+
+               if ((*diffp)->val[A_ATOM] != val)
+                       break;
+
+               diffp = &JT(*diffp);
+               at_top = 0;
+       }
+       samep = &JT(*diffp);
+       while (1) {
+               if (*samep == 0)
+                       return;
+
+               if (JF(*samep) != JF(b))
+                       return;
+
+               if (!SET_MEMBER((*samep)->dom, b->id))
+                       return;
+
+               if ((*samep)->val[A_ATOM] == val)
+                       break;
+
+               /* XXX Need to check that there are no data dependencies
+                  between diffp and samep.  Currently, the code generator
+                  will not produce such dependencies. */
+               samep = &JT(*samep);
+       }
+#ifdef notdef
+       /* XXX This doesn't cover everything. */
+       for (i = 0; i < N_ATOMS; ++i)
+               if ((*samep)->val[i] != pred->val[i])
+                       return;
+#endif
+       /* Pull up the node. */
+       pull = *samep;
+       *samep = JT(pull);
+       JT(pull) = *diffp;
+
+       /*
+        * At the top of the chain, each predecessor needs to point at the
+        * pulled up node.  Inside the chain, there is only one predecessor
+        * to worry about.
+        */
+       if (at_top) {
+               for (ep = b->in_edges; ep != 0; ep = ep->next) {
+                       if (JT(ep->pred) == b)
+                               JT(ep->pred) = pull;
+                       else
+                               JF(ep->pred) = pull;
+               }
+       }
+       else
+               *diffp = pull;
+
+       done = 0;
+}
+
+static void
+opt_blks(root, do_stmts)
+       struct block *root;
+       int do_stmts;
+{
+       int i, maxlevel;
+       struct block *p;
+
+       init_val();
+       maxlevel = root->level;
+       for (i = maxlevel; i >= 0; --i)
+               for (p = levels[i]; p; p = p->link)
+                       opt_blk(p, do_stmts);
+
+       if (do_stmts)
+               /*
+                * No point trying to move branches; it can't possibly
+                * make a difference at this point.
+                */
+               return;
+
+       for (i = 1; i <= maxlevel; ++i) {
+               for (p = levels[i]; p; p = p->link) {
+                       opt_j(&p->et);
+                       opt_j(&p->ef);
+               }
+       }
+       for (i = 1; i <= maxlevel; ++i) {
+               for (p = levels[i]; p; p = p->link) {
+                       or_pullup(p);
+                       and_pullup(p);
+               }
+       }
+}
+
+static __inline void
+link_inedge(parent, child)
+       struct edge *parent;
+       struct block *child;
+{
+       parent->next = child->in_edges;
+       child->in_edges = parent;
+}
+
+static void
+find_inedges(root)
+       struct block *root;
+{
+       int i;
+       struct block *b;
+
+       for (i = 0; i < n_blocks; ++i)
+               blocks[i]->in_edges = 0;
+
+       /*
+        * Traverse the graph, adding each edge to the predecessor
+        * list of its successors.  Skip the leaves (i.e. level 0).
+        */
+       for (i = root->level; i > 0; --i) {
+               for (b = levels[i]; b != 0; b = b->link) {
+                       link_inedge(&b->et, JT(b));
+                       link_inedge(&b->ef, JF(b));
+               }
+       }
+}
+
+static void
+opt_root(b)
+       struct block **b;
+{
+       struct slist *tmp, *s;
+
+       s = (*b)->stmts;
+       (*b)->stmts = 0;
+       while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b))
+               *b = JT(*b);
+
+       tmp = (*b)->stmts;
+       if (tmp != 0)
+               sappend(s, tmp);
+       (*b)->stmts = s;
+
+       /*
+        * If the root node is a return, then there is no
+        * point executing any statements (since the bpf machine
+        * has no side effects).
+        */
+       if (BPF_CLASS((*b)->s.code) == BPF_RET)
+               (*b)->stmts = 0;
+}
+
+static void
+opt_loop(root, do_stmts)
+       struct block *root;
+       int do_stmts;
+{
+
+#ifdef BDEBUG
+       if (dflag > 1)
+               opt_dump(root);
+#endif
+       do {
+               done = 1;
+               find_levels(root);
+               find_dom(root);
+               find_closure(root);
+               find_inedges(root);
+               find_ud(root);
+               find_edom(root);
+               opt_blks(root, do_stmts);
+#ifdef BDEBUG
+               if (dflag > 1)
+                       opt_dump(root);
+#endif
+       } while (!done);
+}
+
+/*
+ * Optimize the filter code in its dag representation.
+ */
+void
+bpf_optimize(rootp)
+       struct block **rootp;
+{
+       struct block *root;
+
+       root = *rootp;
+
+       opt_init(root);
+       opt_loop(root, 0);
+       opt_loop(root, 1);
+       intern_blocks(root);
+       opt_root(rootp);
+       opt_cleanup();
+}
+
+static void
+make_marks(p)
+       struct block *p;
+{
+       if (!isMarked(p)) {
+               Mark(p);
+               if (BPF_CLASS(p->s.code) != BPF_RET) {
+                       make_marks(JT(p));
+                       make_marks(JF(p));
+               }
+       }
+}
+
+/*
+ * Mark code array such that isMarked(i) is true
+ * only for nodes that are alive.
+ */
+static void
+mark_code(p)
+       struct block *p;
+{
+       cur_mark += 1;
+       make_marks(p);
+}
+
+/*
+ * True iff the two stmt lists load the same value from the packet into
+ * the accumulator.
+ */
+static int
+eq_slist(x, y)
+       struct slist *x, *y;
+{
+       while (1) {
+               while (x && x->s.code == NOP)
+                       x = x->next;
+               while (y && y->s.code == NOP)
+                       y = y->next;
+               if (x == 0)
+                       return y == 0;
+               if (y == 0)
+                       return x == 0;
+               if (x->s.code != y->s.code || x->s.k != y->s.k)
+                       return 0;
+               x = x->next;
+               y = y->next;
+       }
+}
+
+static __inline int
+eq_blk(b0, b1)
+       struct block *b0, *b1;
+{
+       if (b0->s.code == b1->s.code &&
+           b0->s.k == b1->s.k &&
+           b0->et.succ == b1->et.succ &&
+           b0->ef.succ == b1->ef.succ)
+               return eq_slist(b0->stmts, b1->stmts);
+       return 0;
+}
+
+static void
+intern_blocks(root)
+       struct block *root;
+{
+       struct block *p;
+       int i, j;
+       int done;
+ top:
+       done = 1;
+       for (i = 0; i < n_blocks; ++i)
+               blocks[i]->link = 0;
+
+       mark_code(root);
+
+       for (i = n_blocks - 1; --i >= 0; ) {
+               if (!isMarked(blocks[i]))
+                       continue;
+               for (j = i + 1; j < n_blocks; ++j) {
+                       if (!isMarked(blocks[j]))
+                               continue;
+                       if (eq_blk(blocks[i], blocks[j])) {
+                               blocks[i]->link = blocks[j]->link ?
+                                       blocks[j]->link : blocks[j];
+                               break;
+                       }
+               }
+       }
+       for (i = 0; i < n_blocks; ++i) {
+               p = blocks[i];
+               if (JT(p) == 0)
+                       continue;
+               if (JT(p)->link) {
+                       done = 0;
+                       JT(p) = JT(p)->link;
+               }
+               if (JF(p)->link) {
+                       done = 0;
+                       JF(p) = JF(p)->link;
+               }
+       }
+       if (!done)
+               goto top;
+}
+
+static void
+opt_cleanup()
+{
+       free((void *)vnode_base);
+       free((void *)vmap);
+       free((void *)edges);
+       free((void *)space);
+       free((void *)levels);
+       free((void *)blocks);
+}
+
+/*
+ * Return the number of stmts in 's'.
+ */
+static int
+slength(s)
+       struct slist *s;
+{
+       int n = 0;
+
+       for (; s; s = s->next)
+               if (s->s.code != NOP)
+                       ++n;
+       return n;
+}
+
+/*
+ * Return the number of nodes reachable by 'p'.
+ * All nodes should be initially unmarked.
+ */
+static int
+count_blocks(p)
+       struct block *p;
+{
+       if (p == 0 || isMarked(p))
+               return 0;
+       Mark(p);
+       return count_blocks(JT(p)) + count_blocks(JF(p)) + 1;
+}
+
+/*
+ * Do a depth first search on the flow graph, numbering the
+ * the basic blocks, and entering them into the 'blocks' array.`
+ */
+static void
+number_blks_r(p)
+       struct block *p;
+{
+       int n;
+
+       if (p == 0 || isMarked(p))
+               return;
+
+       Mark(p);
+       n = n_blocks++;
+       p->id = n;
+       blocks[n] = p;
+
+       number_blks_r(JT(p));
+       number_blks_r(JF(p));
+}
+
+/*
+ * Return the number of stmts in the flowgraph reachable by 'p'.
+ * The nodes should be unmarked before calling.
+ */
+static int
+count_stmts(p)
+       struct block *p;
+{
+       int n;
+
+       if (p == 0 || isMarked(p))
+               return 0;
+       Mark(p);
+       n = count_stmts(JT(p)) + count_stmts(JF(p));
+       return slength(p->stmts) + n + 1;
+}
+
+/*
+ * Allocate memory.  All allocation is done before optimization
+ * is begun.  A linear bound on the size of all data structures is computed
+ * from the total number of blocks and/or statements.
+ */
+static void
+opt_init(root)
+       struct block *root;
+{
+       bpf_u_int32 *p;
+       int i, n, max_stmts;
+
+       /*
+        * First, count the blocks, so we can malloc an array to map
+        * block number to block.  Then, put the blocks into the array.
+        */
+       unMarkAll();
+       n = count_blocks(root);
+       blocks = (struct block **)malloc(n * sizeof(*blocks));
+       unMarkAll();
+       n_blocks = 0;
+       number_blks_r(root);
+
+       n_edges = 2 * n_blocks;
+       edges = (struct edge **)malloc(n_edges * sizeof(*edges));
+
+       /*
+        * The number of levels is bounded by the number of nodes.
+        */
+       levels = (struct block **)malloc(n_blocks * sizeof(*levels));
+
+       edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1;
+       nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
+
+       /* XXX */
+       space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space)
+                                + n_edges * edgewords * sizeof(*space));
+       p = space;
+       all_dom_sets = p;
+       for (i = 0; i < n; ++i) {
+               blocks[i]->dom = p;
+               p += nodewords;
+       }
+       all_closure_sets = p;
+       for (i = 0; i < n; ++i) {
+               blocks[i]->closure = p;
+               p += nodewords;
+       }
+       all_edge_sets = p;
+       for (i = 0; i < n; ++i) {
+               register struct block *b = blocks[i];
+
+               b->et.edom = p;
+               p += edgewords;
+               b->ef.edom = p;
+               p += edgewords;
+               b->et.id = i;
+               edges[i] = &b->et;
+               b->ef.id = n_blocks + i;
+               edges[n_blocks + i] = &b->ef;
+               b->et.pred = b;
+               b->ef.pred = b;
+       }
+       max_stmts = 0;
+       for (i = 0; i < n; ++i)
+               max_stmts += slength(blocks[i]->stmts) + 1;
+       /*
+        * We allocate at most 3 value numbers per statement,
+        * so this is an upper bound on the number of valnodes
+        * we'll need.
+        */
+       maxval = 3 * max_stmts;
+       vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap));
+       vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap));
+}
+
+/*
+ * Some pointers used to convert the basic block form of the code,
+ * into the array form that BPF requires.  'fstart' will point to
+ * the malloc'd array while 'ftail' is used during the recursive traversal.
+ */
+static struct bpf_insn *fstart;
+static struct bpf_insn *ftail;
+
+#ifdef BDEBUG
+int bids[1000];
+#endif
+
+/*
+ * Returns true if successful.  Returns false if a branch has
+ * an offset that is too large.  If so, we have marked that
+ * branch so that on a subsequent iteration, it will be treated
+ * properly.
+ */
+static int
+convert_code_r(p)
+       struct block *p;
+{
+       struct bpf_insn *dst;
+       struct slist *src;
+       int slen;
+       u_int off;
+       int extrajmps;          /* number of extra jumps inserted */
+
+       if (p == 0 || isMarked(p))
+               return (1);
+       Mark(p);
+
+       if (convert_code_r(JF(p)) == 0)
+               return (0);
+       if (convert_code_r(JT(p)) == 0)
+               return (0);
+
+       slen = slength(p->stmts);
+       dst = ftail -= (slen + 1 + p->longjt + p->longjf);
+               /* inflate length by any extra jumps */
+
+       p->offset = dst - fstart;
+
+       for (src = p->stmts; src; src = src->next) {
+               if (src->s.code == NOP)
+                       continue;
+               dst->code = (u_short)src->s.code;
+               dst->k = src->s.k;
+               ++dst;
+       }
+#ifdef BDEBUG
+       bids[dst - fstart] = p->id + 1;
+#endif
+       dst->code = (u_short)p->s.code;
+       dst->k = p->s.k;
+       if (JT(p)) {
+               extrajmps = 0;
+               off = JT(p)->offset - (p->offset + slen) - 1;
+               if (off >= 256) {
+                   /* offset too large for branch, must add a jump */
+                   if (p->longjt == 0) {
+                       /* mark this instruction and retry */
+                       p->longjt++;
+                       return(0);
+                   }
+                   /* branch if T to following jump */
+                   dst->jt = extrajmps;
+                   extrajmps++;
+                   dst[extrajmps].code = BPF_JMP|BPF_JA;
+                   dst[extrajmps].k = off - extrajmps;
+               }
+               else
+                   dst->jt = off;
+               off = JF(p)->offset - (p->offset + slen) - 1;
+               if (off >= 256) {
+                   /* offset too large for branch, must add a jump */
+                   if (p->longjf == 0) {
+                       /* mark this instruction and retry */
+                       p->longjf++;
+                       return(0);
+                   }
+                   /* branch if F to following jump */
+                   /* if two jumps are inserted, F goes to second one */
+                   dst->jf = extrajmps;
+                   extrajmps++;
+                   dst[extrajmps].code = BPF_JMP|BPF_JA;
+                   dst[extrajmps].k = off - extrajmps;
+               }
+               else
+                   dst->jf = off;
+       }
+       return (1);
+}
+
+
+/*
+ * Convert flowgraph intermediate representation to the
+ * BPF array representation.  Set *lenp to the number of instructions.
+ */
+struct bpf_insn *
+icode_to_fcode(root, lenp)
+       struct block *root;
+       int *lenp;
+{
+       int n;
+       struct bpf_insn *fp;
+
+       /*
+        * Loop doing convert_codr_r() until no branches remain
+        * with too-large offsets.
+        */
+       while (1) {
+           unMarkAll();
+           n = *lenp = count_stmts(root);
+    
+           fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
+           memset((char *)fp, 0, sizeof(*fp) * n);
+           fstart = fp;
+           ftail = fp + n;
+    
+           unMarkAll();
+           if (convert_code_r(root))
+               break;
+           free(fp);
+       }
+
+       return fp;
+}
+
+#ifdef BDEBUG
+static void
+opt_dump(root)
+       struct block *root;
+{
+       struct bpf_program f;
+
+       memset(bids, 0, sizeof bids);
+       f.bf_insns = icode_to_fcode(root, &f.bf_len);
+       bpf_dump(&f, 1);
+       putchar('\n');
+       free((char *)f.bf_insns);
+}
+#endif
diff --git a/pcap/pcap-bpf.c b/pcap/pcap-bpf.c
new file mode 100644 (file)
index 0000000..c327b55
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: pcap-bpf.c,v 1.7 1996/09/16 02:33:08 tholo Exp $      */
+
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static  char rcsid[] =
+    "@(#)Header: pcap-bpf.c,v 1.25 96/06/24 02:50:11 leres Exp (LBL)";
+#endif
+
+#include <sys/param.h>                 /* optionally get BSD define */
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+       struct bpf_stat s;
+
+       if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
+               sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno));
+               return (-1);
+       }
+
+       ps->ps_recv = s.bs_recv;
+       ps->ps_drop = s.bs_drop;
+       return (0);
+}
+
+int
+pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       int cc;
+       int n = 0;
+       register u_char *bp, *ep;
+
+ again:
+       cc = p->cc;
+       if (p->cc == 0) {
+               cc = read(p->fd, (char *)p->buffer, p->bufsize);
+               if (cc < 0) {
+                       /* Don't choke when we get ptraced */
+                       switch (errno) {
+
+                       case EINTR:
+                               goto again;
+
+                       case EWOULDBLOCK:
+                               return (0);
+#if defined(sun) && !defined(BSD)
+                       /*
+                        * Due to a SunOS bug, after 2^31 bytes, the kernel
+                        * file offset overflows and read fails with EINVAL.
+                        * The lseek() to 0 will fix things.
+                        */
+                       case EINVAL:
+                               if (lseek(p->fd, 0L, SEEK_CUR) +
+                                   p->bufsize < 0) {
+                                       (void)lseek(p->fd, 0L, SEEK_SET);
+                                       goto again;
+                               }
+                               /* fall through */
+#endif
+                       }
+                       sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
+                       return (-1);
+               }
+               bp = p->buffer;
+       } else
+               bp = p->bp;
+
+       /*
+        * Loop through each packet.
+        */
+#define bhp ((struct bpf_hdr *)bp)
+       ep = bp + cc;
+       while (bp < ep) {
+               register int caplen, hdrlen;
+               caplen = bhp->bh_caplen;
+               hdrlen = bhp->bh_hdrlen;
+               /*
+                * XXX A bpf_hdr matches a pcap_pkthdr.
+                */
+               (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
+               bp += BPF_WORDALIGN(caplen + hdrlen);
+               if (++n >= cnt && cnt > 0) {
+                       p->bp = bp;
+                       p->cc = ep - bp;
+                       return (n);
+               }
+       }
+#undef bhp
+       p->cc = 0;
+       return (n);
+}
+
+int
+pcap_inject(pcap_t *p, const void *buf, size_t len)
+{
+       return (write(p->fd, buf, len));
+}
+
+static __inline int
+bpf_open(pcap_t *p, char *errbuf)
+{
+       int fd;
+       int n = 0;
+       char device[sizeof "/dev/bpf000"];
+
+       /*
+        * Go through all the minors and find one that isn't in use.
+        */
+       do {
+               (void)sprintf(device, "/dev/bpf%d", n++);
+               fd = open(device, O_RDONLY);
+       } while (fd < 0 && errno == EBUSY);
+
+       /*
+        * XXX better message for all minors used
+        */
+       if (fd < 0)
+               sprintf(errbuf, "%s: %s", device, pcap_strerror(errno));
+
+       return (fd);
+}
+
+pcap_t *
+pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+{
+       int fd;
+       struct ifreq ifr;
+       struct bpf_version bv;
+       u_int v;
+       pcap_t *p;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               return (NULL);
+       }
+       bzero(p, sizeof(*p));
+       fd = bpf_open(p, ebuf);
+       if (fd < 0)
+               goto bad;
+
+       p->fd = fd;
+       p->snapshot = snaplen;
+
+       if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
+               sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       if (bv.bv_major != BPF_MAJOR_VERSION ||
+           bv.bv_minor < BPF_MINOR_VERSION) {
+               sprintf(ebuf, "kernel bpf filter out of date");
+               goto bad;
+       }
+       (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+       if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+               sprintf(ebuf, "%s: %s", device, pcap_strerror(errno));
+               goto bad;
+       }
+       /* Get the data link layer type. */
+       if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
+               sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->linktype = v;
+
+       /* set timeout */
+       if (to_ms != 0) {
+               struct timeval to;
+               to.tv_sec = to_ms / 1000;
+               to.tv_usec = (to_ms * 1000) % 1000000;
+               if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
+                       sprintf(ebuf, "BIOCSRTIMEOUT: %s",
+                               pcap_strerror(errno));
+                       goto bad;
+               }
+       }
+       if (promisc)
+               /* set promiscuous mode, okay if it fails */
+               (void)ioctl(p->fd, BIOCPROMISC, NULL);
+
+       if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
+               sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       p->bufsize = v;
+       p->buffer = (u_char *)malloc(p->bufsize);
+       if (p->buffer == NULL) {
+               sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
+               goto bad;
+       }
+
+       return (p);
+ bad:
+       (void)close(fd);
+       free(p);
+       return (NULL);
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+       if (p->sf.rfile != NULL)
+               p->fcode = *fp;
+       else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
+               sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
diff --git a/pcap/pcap-int.h b/pcap/pcap-int.h
new file mode 100644 (file)
index 0000000..9513df1
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: pcap-int.h,v 1.6 1996/08/03 12:38:44 niklas Exp $     */
+
+/*
+ * Copyright (c) 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: pcap-int.h,v 1.14 95/10/21 22:04:49 leres Exp (LBL)
+ */
+
+#ifndef pcap_int_h
+#define pcap_int_h
+
+#include <pcap.h>
+
+/*
+ * Savefile
+ */
+struct pcap_sf {
+       FILE *rfile;
+       int swapped;
+       int version_major;
+       int version_minor;
+       u_char *base;
+};
+
+struct pcap_md {
+       struct pcap_stat stat;
+       /*XXX*/
+       int use_bpf;
+       u_long  TotPkts;        /* can't oflow for 79 hrs on ether */
+       u_long  TotAccepted;    /* count accepted by filter */
+       u_long  TotDrops;       /* count of dropped packets */
+       long    TotMissed;      /* missed by i/f during this run */
+       long    OrigMissed;     /* missed by i/f before this run */
+};
+
+struct pcap {
+       int fd;
+       int snapshot;
+       int linktype;
+       int tzoff;              /* timezone offset */
+
+       struct pcap_sf sf;
+       struct pcap_md md;
+
+       /*
+        * Read buffer.
+        */
+       int bufsize;
+       u_char *buffer;
+       u_char *bp;
+       int cc;
+
+       /*
+        * Place holder for pcap_next().
+        */
+       u_char *pkt;
+
+       
+       /*
+        * Placeholder for filter code if bpf not in kernel.
+        */
+       struct bpf_program fcode;
+
+       char errbuf[PCAP_ERRBUF_SIZE];
+};
+
+int    yylex(void);
+
+/* XXX should these be in pcap.h? */
+int    pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
+int    pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
+
+/* Ultrix pads to make everything line up on a nice boundary */
+#if defined(ultrix) || defined(__alpha)
+#define       PCAP_FDDIPAD 3
+#endif
+#endif
diff --git a/pcap/pcap-namedb.h b/pcap/pcap-namedb.h
new file mode 100644 (file)
index 0000000..d8bf162
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: pcap-namedb.h,v 1.4 1996/07/12 13:19:11 mickey Exp $  */
+
+/*
+ * Copyright (c) 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: pcap-namedb.h,v 1.4 96/06/23 02:21:08 leres Exp (LBL)
+ */
+
+#ifndef lib_pcap_ethers_h
+#define lib_pcap_ethers_h
+
+/*
+ * As returned by the pcap_next_etherent()
+ * XXX this stuff doesn't belong in this interface, but this
+ * library already must do name to address translation, so
+ * on systems that don't have support for /etc/ethers, we
+ * export these hooks since they'll
+ */
+struct pcap_etherent {
+       u_char addr[6];
+       char name[122];
+};
+#ifndef PCAP_ETHERS_FILE
+#define PCAP_ETHERS_FILE "/etc/ethers"
+#endif
+struct pcap_etherent *pcap_next_etherent(FILE *);
+u_char *pcap_ether_hostton(const char*);
+u_char *pcap_ether_aton(const char *);
+
+bpf_u_int32 **pcap_nametoaddr(const char *);
+bpf_u_int32 pcap_nametonetaddr(const char *);
+
+int    pcap_nametoport(const char *, int *, int *);
+int    pcap_nametoproto(const char *);
+int    pcap_nametoeproto(const char *);
+/*
+ * If a protocol is unknown, PROTO_UNDEF is returned.
+ * Also, pcap_nametoport() returns the protocol along with the port number.
+ * If there are ambiguous entried in /etc/services (i.e. domain
+ * can be either tcp or udp) PROTO_UNDEF is returned.
+ */
+#define PROTO_UNDEF            -1
+
+/* XXX move these to pcap-int.h? */
+bpf_u_int32 __pcap_atodn(const char *);
+bpf_u_int32 __pcap_atoin(const char *);
+u_short        __pcap_nametodnaddr(const char *);
+
+#endif
diff --git a/pcap/pcap.c b/pcap/pcap.c
new file mode 100644 (file)
index 0000000..c34b0b2
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: pcap.c,v 1.4 1996/07/12 13:19:12 mickey Exp $ */
+
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+    "@(#) Header: pcap.c,v 1.25 96/06/05 21:45:26 leres Exp (LBL)";
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+int
+pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       register int cc;
+
+       if (p->sf.rfile != NULL)
+               return (pcap_offline_read(p, cnt, callback, user));
+       /* XXX keep reading until we get something (or an error occurs) */
+       do {
+               cc = pcap_read(p, cnt, callback, user);
+       } while (cc == 0);
+       return (cc);
+}
+
+int
+pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       for (;;) {
+               int n = pcap_dispatch(p, cnt, callback, user);
+               if (n <= 0)
+                       return (n);
+               if (cnt > 0) {
+                       cnt -= n;
+                       if (cnt <= 0)
+                               return (0);
+               }
+       }
+}
+
+struct singleton {
+       struct pcap_pkthdr *hdr;
+       const u_char *pkt;
+};
+
+
+static void
+pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
+{
+       struct singleton *sp = (struct singleton *)userData;
+       *sp->hdr = *h;
+       sp->pkt = pkt;
+}
+
+const u_char *
+pcap_next(pcap_t *p, struct pcap_pkthdr *h)
+{
+       struct singleton s;
+
+       s.hdr = h;
+       if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
+               return (0);
+       return (s.pkt);
+}
+
+int
+pcap_datalink(pcap_t *p)
+{
+       return (p->linktype);
+}
+
+int
+pcap_snapshot(pcap_t *p)
+{
+       return (p->snapshot);
+}
+
+int
+pcap_is_swapped(pcap_t *p)
+{
+       return (p->sf.swapped);
+}
+
+int
+pcap_major_version(pcap_t *p)
+{
+       return (p->sf.version_major);
+}
+
+int
+pcap_minor_version(pcap_t *p)
+{
+       return (p->sf.version_minor);
+}
+
+FILE *
+pcap_file(pcap_t *p)
+{
+       return (p->sf.rfile);
+}
+
+int
+pcap_fileno(pcap_t *p)
+{
+       return (p->fd);
+}
+
+void
+pcap_perror(pcap_t *p, char *prefix)
+{
+       fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
+}
+
+char *
+pcap_geterr(pcap_t *p)
+{
+       return (p->errbuf);
+}
+
+/*
+ * Not all systems have strerror().
+ */
+char *
+pcap_strerror(int errnum)
+{
+#ifdef HAVE_STRERROR
+       return (strerror(errnum));
+#else
+       extern int sys_nerr;
+       extern const char *const sys_errlist[];
+       static char ebuf[20];
+
+       if ((unsigned int)errnum < sys_nerr)
+               return ((char *)sys_errlist[errnum]);
+       (void)sprintf(ebuf, "Unknown error: %d", errnum);
+       return(ebuf);
+#endif
+}
+
+void
+pcap_close(pcap_t *p)
+{
+       /*XXX*/
+       if (p->fd >= 0)
+               close(p->fd);
+       if (p->sf.rfile != NULL) {
+               (void)fclose(p->sf.rfile);
+               if (p->sf.base != NULL)
+                       free(p->sf.base);
+       } else if (p->buffer != NULL)
+               free(p->buffer);
+       
+       free(p);
+}
diff --git a/pcap/pcap.h b/pcap/pcap.h
new file mode 100644 (file)
index 0000000..46db423
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: pcap.h,v 1.6 1996/07/12 13:19:12 mickey Exp $ */
+
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: pcap.h,v 1.19 96/06/16 22:36:28 leres Exp (LBL)
+ */
+
+#ifndef lib_pcap_h
+#define lib_pcap_h
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <net/bpf.h>
+
+#include <stdio.h>
+
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+#define PCAP_ERRBUF_SIZE 256
+
+/*
+ * Compatibility for systems that have a bpf.h that
+ * predates the bpf typedefs for 64-bit support.
+ */
+#if BPF_RELEASE - 0 < 199406
+typedef        int bpf_int32;
+typedef        u_int bpf_u_int32;
+#endif
+
+typedef struct pcap pcap_t;
+typedef struct pcap_dumper pcap_dumper_t;
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are 32 bit ints so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ */
+struct pcap_file_header {
+       bpf_u_int32 magic;
+       u_short version_major;
+       u_short version_minor;
+       bpf_int32 thiszone;     /* gmt to local correction */
+       bpf_u_int32 sigfigs;    /* accuracy of timestamps */
+       bpf_u_int32 snaplen;    /* max length saved portion of each pkt */
+       bpf_u_int32 linktype;   /* data link type (DLT_*) */
+};
+
+/*
+ * Each packet in the dump file is prepended with this generic header.
+ * This gets around the problem of different headers for different
+ * packet interfaces.
+ */
+struct pcap_pkthdr {
+       struct timeval ts;      /* time stamp */
+       bpf_u_int32 caplen;     /* length of portion present */
+       bpf_u_int32 len;        /* length this packet (off wire) */
+};
+
+/*
+ * As returned by the pcap_stats()
+ */
+struct pcap_stat {
+       u_int ps_recv;          /* number of packets received */
+       u_int ps_drop;          /* number of packets dropped */
+       u_int ps_ifdrop;        /* drops by interface XXX not yet supported */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+                            const u_char *);
+
+char   *pcap_lookupdev(char *);
+int    pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+pcap_t *pcap_open_live(char *, int, int, int, char *);
+pcap_t *pcap_open_offline(char *, char *);
+void   pcap_close(pcap_t *);
+int    pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+int    pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+const u_char*
+       pcap_next(pcap_t *, struct pcap_pkthdr *);
+int    pcap_stats(pcap_t *, struct pcap_stat *);
+int    pcap_setfilter(pcap_t *, struct bpf_program *);
+void   pcap_perror(pcap_t *, char *);
+char   *pcap_strerror(int);
+char   *pcap_geterr(pcap_t *);
+int    pcap_compile(pcap_t *, struct bpf_program *, char *, int,
+           bpf_u_int32);
+/* XXX */
+int    pcap_freecode(pcap_t *, struct bpf_program *);
+int    pcap_datalink(pcap_t *);
+int    pcap_snapshot(pcap_t *);
+int    pcap_is_swapped(pcap_t *);
+int    pcap_major_version(pcap_t *);
+int    pcap_minor_version(pcap_t *);
+
+/* XXX */
+FILE   *pcap_file(pcap_t *);
+int    pcap_fileno(pcap_t *);
+
+pcap_dumper_t *pcap_dump_open(pcap_t *, char *);
+void   pcap_dump_close(pcap_dumper_t *);
+void   pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+/* XXX this guy lives in the bpf tree */
+u_int  bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+char   *bpf_image(struct bpf_insn *, int);
+
+/* XXX */
+extern int pcap_fddipad;
+
+#endif
diff --git a/pcap/savefile.c b/pcap/savefile.c
new file mode 100644 (file)
index 0000000..ba1e9c0
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: savefile.c,v 1.4 1996/07/12 13:19:13 mickey Exp $     */
+
+/*
+ * Copyright (c) 1993, 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static char rcsid[] =
+    "@(#)Header: savefile.c,v 1.28 95/10/07 03:09:06 leres Exp (LBL)";
+#endif
+
+/*
+ * savefile.c - supports offline use of tcpdump
+ *     Extraction/creation by Jeffrey Mogul, DECWRL
+ *     Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <net/bpf.h>
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+/*
+ * We use the "receiver-makes-right" approach to byte order,
+ * because time is at a premium when we are writing the file.
+ * In other words, the pcap_file_header and pcap_pkthdr,
+ * records are written in host byte order.
+ * Note that the packets are always written in network byte order.
+ *
+ * ntoh[ls] aren't sufficient because we might need to swap on a big-endian
+ * machine (if the file was written in little-end order).
+ */
+#define        SWAPLONG(y) \
+((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+#define        SWAPSHORT(y) \
+       ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
+
+#define SFERR_TRUNC            1
+#define SFERR_BADVERSION       2
+#define SFERR_BADF             3
+#define SFERR_EOF              4 /* not really an error, just a status */
+
+static int
+sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
+{
+       struct pcap_file_header hdr;
+
+       hdr.magic = TCPDUMP_MAGIC;
+       hdr.version_major = PCAP_VERSION_MAJOR;
+       hdr.version_minor = PCAP_VERSION_MINOR;
+
+       hdr.thiszone = thiszone;
+       hdr.snaplen = snaplen;
+       hdr.sigfigs = 0;
+       hdr.linktype = linktype;
+
+       if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
+               return (-1);
+
+       return (0);
+}
+
+static void
+swap_hdr(struct pcap_file_header *hp)
+{
+       hp->version_major = SWAPSHORT(hp->version_major);
+       hp->version_minor = SWAPSHORT(hp->version_minor);
+       hp->thiszone = SWAPLONG(hp->thiszone);
+       hp->sigfigs = SWAPLONG(hp->sigfigs);
+       hp->snaplen = SWAPLONG(hp->snaplen);
+       hp->linktype = SWAPLONG(hp->linktype);
+}
+
+pcap_t *
+pcap_open_offline(char *fname, char *errbuf)
+{
+       register pcap_t *p;
+       register FILE *fp;
+       struct pcap_file_header hdr;
+       int linklen;
+
+       p = (pcap_t *)malloc(sizeof(*p));
+       if (p == NULL) {
+               strcpy(errbuf, "out of swap");
+               return (NULL);
+       }
+
+       memset((char *)p, 0, sizeof(*p));
+       /*
+        * Set this field so we don't close stdin in pcap_close!
+        */
+       p->fd = -1;
+
+       if (fname[0] == '-' && fname[1] == '\0')
+               fp = stdin;
+       else {
+               fp = fopen(fname, "r");
+               if (fp == NULL) {
+                       sprintf(errbuf, "%s: %s", fname, pcap_strerror(errno));
+                       goto bad;
+               }
+       }
+       if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
+               sprintf(errbuf, "fread: %s", pcap_strerror(errno));
+               goto bad;
+       }
+       if (hdr.magic != TCPDUMP_MAGIC) {
+               if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) {
+                       sprintf(errbuf, "bad dump file format");
+                       goto bad;
+               }
+               p->sf.swapped = 1;
+               swap_hdr(&hdr);
+       }
+       if (hdr.version_major < PCAP_VERSION_MAJOR) {
+               sprintf(errbuf, "archaic file format");
+               goto bad;
+       }
+       p->tzoff = hdr.thiszone;
+       p->snapshot = hdr.snaplen;
+       p->linktype = hdr.linktype;
+       p->sf.rfile = fp;
+       p->bufsize = hdr.snaplen;
+
+       /* Align link header as required for proper data alignment */
+       /* XXX should handle all types */
+       switch (p->linktype) {
+
+       case DLT_EN10MB:
+               linklen = 14;
+               break;
+
+       case DLT_FDDI:
+               linklen = 13 + 8;       /* fddi_header + llc */
+               break;
+
+       case DLT_NULL:
+       default:
+               linklen = 0;
+               break;
+       }
+
+       p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT);
+       p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT);
+       p->sf.version_major = hdr.version_major;
+       p->sf.version_minor = hdr.version_minor;
+
+       return (p);
+ bad:
+       free(p);
+       return (NULL);
+}
+
+/*
+ * Read sf_readfile and return the next packet.  Return the header in hdr
+ * and the contents in buf.  Return 0 on success, SFERR_EOF if there were
+ * no more packets, and SFERR_TRUNC if a partial packet was encountered.
+ */
+static int
+sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen)
+{
+       FILE *fp = p->sf.rfile;
+
+       /* read the stamp */
+       if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) {
+               /* probably an EOF, though could be a truncated packet */
+               return (1);
+       }
+
+       if (p->sf.swapped) {
+               /* these were written in opposite byte order */
+               hdr->caplen = SWAPLONG(hdr->caplen);
+               hdr->len = SWAPLONG(hdr->len);
+               hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
+               hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
+       }
+       /*
+        * We interchanged the caplen and len fields at version 2.3,
+        * in order to match the bpf header layout.  But unfortunately
+        * some files were written with version 2.3 in their headers
+        * but without the interchanged fields.
+        */
+       if (p->sf.version_minor < 3 ||
+           (p->sf.version_minor == 3 && hdr->caplen > hdr->len)) {
+               int t = hdr->caplen;
+               hdr->caplen = hdr->len;
+               hdr->len = t;
+       }
+
+       if (hdr->caplen > buflen) {
+               /*
+                * This can happen due to Solaris 2.3 systems tripping
+                * over the BUFMOD problem and not setting the snapshot
+                * correctly in the savefile header.  If the caplen isn't
+                * grossly wrong, try to salvage.
+                */
+               static u_char *tp = NULL;
+               static int tsize = 0;
+
+               if (tsize < hdr->caplen) {
+                       tsize = ((hdr->caplen + 1023) / 1024) * 1024;
+                       if (tp != NULL)
+                               free((u_char *)tp);
+                       tp = (u_char *)malloc(tsize);
+                       if (tp == NULL) {
+                               sprintf(p->errbuf, "BUFMOD hack malloc");
+                               return (-1);
+                       }
+               }
+               if (fread((char *)tp, hdr->caplen, 1, fp) != 1) {
+                       sprintf(p->errbuf, "truncated dump file");
+                       return (-1);
+               }
+               memcpy((char *)buf, (char *)tp, buflen);
+
+       } else {
+               /* read the packet itself */
+
+               if (fread((char *)buf, hdr->caplen, 1, fp) != 1) {
+                       sprintf(p->errbuf, "truncated dump file");
+                       return (-1);
+               }
+       }
+       return (0);
+}
+
+/*
+ * Print out packets stored in the file initialized by sf_read_init().
+ * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
+ */
+int
+pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+       struct bpf_insn *fcode = p->fcode.bf_insns;
+       int status = 0;
+       int n = 0;
+
+       while (status == 0) {
+               struct pcap_pkthdr h;
+
+               status = sf_next_packet(p, &h, p->buffer, p->bufsize);
+               if (status) {
+                       if (status == 1)
+                               return (0);
+                       return (status);
+               }
+
+               if (fcode == NULL ||
+                   bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
+                       (*callback)(user, &h, p->buffer);
+                       if (++n >= cnt && cnt > 0)
+                               break;
+               }
+       }
+       /*XXX this breaks semantics tcpslice expects */
+       return (n);
+}
+
+/*
+ * Output a packet to the initialized dump file.
+ */
+void
+pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+{
+       register FILE *f;
+
+       f = (FILE *)user;
+       /* XXX we should check the return status */
+       (void)fwrite((char *)h, sizeof(*h), 1, f);
+       (void)fwrite((char *)sp, h->caplen, 1, f);
+}
+
+/*
+ * Initialize so that sf_write() will output to the file named 'fname'.
+ */
+pcap_dumper_t *
+pcap_dump_open(pcap_t *p, char *fname)
+{
+       FILE *f;
+       if (fname[0] == '-' && fname[1] == '\0')
+               f = stdout;
+       else {
+               f = fopen(fname, "w");
+               if (f == NULL) {
+                       sprintf(p->errbuf, "%s: %s",
+                           fname, pcap_strerror(errno));
+                       return (NULL);
+               }
+       }
+       (void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot);
+       return ((pcap_dumper_t *)f);
+}
+
+void
+pcap_dump_close(pcap_dumper_t *p)
+{
+
+#ifdef notyet
+       if (ferror((FILE *)p))
+               return-an-error;
+       /* XXX should check return from fclose() too */
+#endif
+       (void)fclose((FILE *)p);
+}
diff --git a/pcap/scanner.l b/pcap/scanner.l
new file mode 100644 (file)
index 0000000..2cbb693
--- /dev/null
@@ -0,0 +1,198 @@
+%{
+/*     $OpenBSD: scanner.l,v 1.5 1996/07/12 13:19:13 mickey Exp $      */
+
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/pcap/scanner.l,v 1.1.1.1 1999/05/02 03:57:55 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <unistd.h>
+
+#include <pcap.h>
+#include <pcap-namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "pcap-int.h"
+#include "gencode.h"
+#include "y.tab.h"
+
+static int stoi(char *);
+static inline int xdtoi(int);
+
+#ifdef FLEX_SCANNER
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max)\
+ {\
+       char *src = in_buffer;\
+       int i;\
+\
+       if (*src == 0)\
+               result = YY_NULL;\
+       else {\
+               for (i = 0; *src && i < max; ++i)\
+                       buf[i] = *src++;\
+               in_buffer += i;\
+               result = i;\
+       }\
+ }
+#else
+#undef getc
+#define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
+#endif
+
+extern YYSTYPE yylval;
+
+static char *in_buffer;
+
+%}
+
+N              ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+B              ([0-9A-Fa-f][0-9A-Fa-f]?)
+
+%a 3000
+
+%%
+dst            return DST;
+src            return SRC;
+
+link|ether|ppp|slip  return LINK;
+fddi           return LINK;
+arp            return ARP;
+rarp           return RARP;
+ip             return IP;
+tcp            return TCP;
+udp            return UDP;
+icmp           return ICMP;
+igmp           return IGMP;
+
+decnet         return DECNET;
+lat            return LAT;
+moprc          return MOPRC;
+mopdl          return MOPDL;
+
+host           return HOST;
+net            return NET;
+port           return PORT;
+proto          return PROTO;
+
+gateway                return GATEWAY;
+
+less           return LESS;
+greater                return GREATER;
+byte           return BYTE;
+broadcast      return TK_BROADCAST;
+multicast      return TK_MULTICAST;
+
+and|"&&"       return AND;
+or|"||"                return OR;
+not            return '!';
+
+len|length     return LEN;
+inbound                return INBOUND;
+outbound       return OUTBOUND;
+
+[ \n\t]                        ;
+[+\-*/:\[\]!<>()&|=]   return yytext[0];
+">="                   return GEQ;
+"<="                   return LEQ;
+"!="                   return NEQ;
+"=="                   return '=';
+"<<"                   return LSH;
+">>"                   return RSH;
+{N}                    { yylval.i = stoi((char *)yytext); return NUM; }
+({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N})        {
+                       yylval.s = sdup((char *)yytext); return HID;
+}
+{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext);
+                         return EID; }
+{B}:+({B}:+)+          { bpf_error("bogus ethernet address %s", yytext); }
+[A-Za-z][-_.A-Za-z0-9]*        { yylval.s = sdup((char *)yytext); return ID; }
+"\\"[^ !()\n\t]+       { yylval.s = sdup((char *)yytext + 1); return ID; }
+[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+    { bpf_error("illegal token: %s\n", yytext); }
+.                      { bpf_error("illegal char '%c'", *yytext); }
+%%
+void
+lex_init(buf)
+       char *buf;
+{
+       in_buffer = buf;
+}
+
+/*
+ * Also define a yywrap.  Note that if we're using flex, it will
+ * define a macro to map this identifier to pcap_wrap.
+ */
+int
+yywrap()
+{
+       return 1;
+}
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(c)
+       register int c;
+{
+       if (isdigit(c))
+               return c - '0';
+       else if (islower(c))
+               return c - 'a' + 10;
+       else
+               return c - 'A' + 10;
+}
+
+/*
+ * Convert string to integer.  Just like atoi(), but checks for
+ * preceding 0x or 0 and uses hex or octal instead of decimal.
+ */
+static int
+stoi(s)
+       char *s;
+{
+       int base = 10;
+       int n = 0;
+
+       if (*s == '0') {
+               if (s[1] == 'x' || s[1] == 'X') {
+                       s += 2;
+                       base = 16;
+               }
+               else {
+                       base = 8;
+                       s += 1;
+               }
+       }
+       while (*s)
+               n = n * base + xdtoi(*s++);
+
+       return n;
+}
+
diff --git a/ping.tproj/Makefile b/ping.tproj/Makefile
new file mode 100644 (file)
index 0000000..8ad77bf
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ping
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ping.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            ping.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ping.tproj/Makefile.dist b/ping.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..d08f74d
--- /dev/null
@@ -0,0 +1,8 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  ping
+MAN8=  ping.0
+BINOWN=        root
+BINMODE=4555
+
+.include <bsd.prog.mk>
diff --git a/ping.tproj/Makefile.postamble b/ping.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..23e0214
--- /dev/null
@@ -0,0 +1 @@
+INSTALL_PERMISSIONS = 4555  # If set, 'install' chmod's executable to this
diff --git a/ping.tproj/Makefile.preamble b/ping.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/ping.tproj/PB.project b/ping.tproj/PB.project
new file mode 100644 (file)
index 0000000..b7fd3c5
--- /dev/null
@@ -0,0 +1,31 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (ping.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, ping.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = ping; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = ping; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ping; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = ping; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ping.tproj/ping.8 b/ping.tproj/ping.8
new file mode 100644 (file)
index 0000000..2382365
--- /dev/null
@@ -0,0 +1,328 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)ping.8     8.3 (Berkeley) 4/28/95
+.\"
+.Dd April 28, 1995
+.Dt PING 8
+.Os BSD 4.3
+.Sh NAME
+.Nm ping
+.Nd send
+.Tn ICMP ECHO_REQUEST
+packets to network hosts
+.Sh SYNOPSIS
+.Nm ping
+.Op Fl Rdfnqrv
+.Op Fl c Ar count
+.Op Fl i Ar wait
+.Op Fl l Ar preload
+.Op Fl p Ar pattern
+.Op Fl s Ar packetsize
+.Ar host
+.Sh DESCRIPTION
+.Nm Ping
+uses the
+.Tn ICMP
+protocol's mandatory
+.Tn ECHO_REQUEST
+datagram to elicit an
+.Tn ICMP ECHO_RESPONSE
+from a host or gateway.
+.Tn ECHO_REQUEST
+datagrams (``pings'') have an IP and
+.Tn ICMP
+header,
+followed by a
+.Dq struct timeval
+and then an arbitrary number of ``pad'' bytes used to fill out the
+packet.
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c Ar count
+Stop after sending (and receiving)
+.Ar count
+.Tn ECHO_RESPONSE
+packets.
+.It Fl d
+Set the
+.Dv SO_DEBUG
+option on the socket being used.
+.It Fl f
+Flood ping.
+Outputs packets as fast as they come back or one hundred times per second,
+whichever is more.
+For every
+.Tn ECHO_REQUEST
+sent a period ``.'' is printed, while for every
+.Tn ECHO_REPLY
+received a backspace is printed.
+This provides a rapid display of how many packets are being dropped.
+Only the super-user may use this option.
+.Bf -emphasis
+This can be very hard on a network and should be used with caution.
+.Ef
+.It Fl i Ar wait
+Wait
+.Ar wait
+seconds
+.Em between sending each packet .
+The default is to wait for one second between each packet.
+This option is incompatible with the
+.Fl f
+option.
+.It Fl l Ar preload
+If
+.Ar preload
+is specified,
+.Nm ping
+sends that many packets as fast as possible before falling into its normal
+mode of behavior.
+.It Fl n
+Numeric output only.
+No attempt will be made to lookup symbolic names for host addresses.
+.It Fl p Ar pattern
+You may specify up to 16 ``pad'' bytes to fill out the packet you send.
+This is useful for diagnosing data-dependent problems in a network.
+For example,
+.Dq Li \-p ff
+will cause the sent packet to be filled with all
+ones.
+.It Fl q
+Quiet output.
+Nothing is displayed except the summary lines at startup time and
+when finished.
+.It Fl R
+Record route.
+Includes the
+.Tn RECORD_ROUTE
+option in the
+.Tn ECHO_REQUEST
+packet and displays
+the route buffer on returned packets.
+Note that the IP header is only large enough for nine such routes.
+Many hosts ignore or discard this option.
+.It Fl r
+Bypass the normal routing tables and send directly to a host on an attached
+network.
+If the host is not on a directly-attached network, an error is returned.
+This option can be used to ping a local host through an interface
+that has no route through it (e.g., after the interface was dropped by
+.Xr routed 8 ) .
+.It Fl s Ar packetsize
+Specifies the number of data bytes to be sent.  
+The default is 56, which translates into 64
+.Tn ICMP
+data bytes when combined
+with the 8 bytes of
+.Tn ICMP
+header data.
+.It Fl v
+Verbose output.
+.Tn ICMP
+packets other than
+.Tn ECHO_RESPONSE
+that are received are listed.
+.El
+.Pp
+When using
+.Nm ping
+for fault isolation, it should first be run on the local host, to verify
+that the local network interface is up and running.
+Then, hosts and gateways further and further away should be ``pinged''.
+Round-trip times and packet loss statistics are computed.
+If duplicate packets are received, they are not included in the packet
+loss calculation, although the round trip time of these packets is used
+in calculating the minimum/average/maximum round-trip time numbers.
+When the specified number of packets have been sent (and received) or
+if the program is terminated with a
+.Dv SIGINT ,
+a brief summary is displayed.
+.Pp
+This program is intended for use in network testing, measurement and
+management.
+Because of the load it can impose on the network, it is unwise to use
+.Nm ping
+during normal operations or from automated scripts.
+.Sh ICMP PACKET DETAILS
+An IP header without options is 20 bytes.
+An
+.Tn ICMP
+.Tn ECHO_REQUEST
+packet contains an additional 8 bytes worth
+of
+.Tn ICMP
+header followed by an arbitrary amount of data.
+When a
+.Ar packetsize
+is given, this indicated the size of this extra piece of data (the
+default is 56).
+Thus the amount of data received inside of an IP packet of type
+.Tn ICMP
+.Tn ECHO_REPLY
+will always be 8 bytes more than the requested data space
+(the
+.Tn ICMP
+header).
+.Pp
+If the data space is at least eight bytes large,
+.Nm ping
+uses the first eight bytes of this space to include a timestamp which
+it uses in the computation of round trip times.
+If less than eight bytes of pad are specified, no round trip times are
+given.
+.Sh DUPLICATE AND DAMAGED PACKETS
+.Nm Ping
+will report duplicate and damaged packets.
+Duplicate packets should never occur, and seem to be caused by
+inappropriate link-level retransmissions.
+Duplicates may occur in many situations and are rarely (if ever) a
+good sign, although the presence of low levels of duplicates may not
+always be cause for alarm.
+.Pp
+Damaged packets are obviously serious cause for alarm and often
+indicate broken hardware somewhere in the
+.Nm ping
+packet's path (in the network or in the hosts).
+.Sh TRYING DIFFERENT DATA PATTERNS
+The (inter)network layer should never treat packets differently depending
+on the data contained in the data portion.
+Unfortunately, data-dependent problems have been known to sneak into
+networks and remain undetected for long periods of time.
+In many cases the particular pattern that will have problems is something
+that doesn't have sufficient ``transitions'', such as all ones or all
+zeros, or a pattern right at the edge, such as almost all zeros.
+It isn't necessarily enough to specify a data pattern of all zeros (for
+example) on the command line because the pattern that is of interest is
+at the data link level, and the relationship between what you type and
+what the controllers transmit can be complicated.
+.Pp
+This means that if you have a data-dependent problem you will probably
+have to do a lot of testing to find it.
+If you are lucky, you may manage to find a file that either can't be sent
+across your network or that takes much longer to transfer than other
+similar length files.
+You can then examine this file for repeated patterns that you can test
+using the
+.Fl p
+option of
+.Nm ping .
+.Sh TTL DETAILS
+The
+.Tn TTL
+value of an IP packet represents the maximum number of IP routers
+that the packet can go through before being thrown away.
+In current practice you can expect each router in the Internet to decrement
+the
+.Tn TTL
+field by exactly one.
+.Pp
+The
+.Tn TCP/IP
+specification states that the
+.Tn TTL
+field for
+.Tn TCP
+packets should
+be set to 60, but many systems use smaller values (4.3
+.Tn BSD
+uses 30, 4.2 used
+15).
+.Pp
+The maximum possible value of this field is 255, and most Unix systems set
+the
+.Tn TTL
+field of
+.Tn ICMP ECHO_REQUEST
+packets to 255.
+This is why you will find you can ``ping'' some hosts, but not reach them
+with
+.Xr telnet 1
+or
+.Xr ftp 1 .
+.Pp
+In normal operation ping prints the ttl value from the packet it receives.
+When a remote system receives a ping packet, it can do one of three things
+with the
+.Tn TTL
+field in its response:
+.Bl -bullet
+.It
+Not change it; this is what Berkeley Unix systems did before the
+.Bx 4.3 tahoe
+release.
+In this case the
+.Tn TTL
+value in the received packet will be 255 minus the
+number of routers in the round-trip path.
+.It
+Set it to 255; this is what current Berkeley Unix systems do.
+In this case the
+.Tn TTL
+value in the received packet will be 255 minus the
+number of routers in the path
+.Xr from
+the remote system
+.Em to
+the
+.Nm ping Ns Em ing
+host.
+.It
+Set it to some other value.
+Some machines use the same value for
+.Tn ICMP
+packets that they use for
+.Tn TCP
+packets, for example either 30 or 60.
+Others may use completely wild values.
+.El
+.Sh BUGS
+Many Hosts and Gateways ignore the
+.Tn RECORD_ROUTE
+option.
+.Pp
+The maximum IP header length is too small for options like
+.Tn RECORD_ROUTE
+to
+be completely useful.
+There's not much that that can be done about this, however.
+.Pp
+Flood pinging is not recommended in general, and flood pinging the
+broadcast address should only be done under very controlled conditions.
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr ifconfig 8 ,
+.Xr routed 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/ping.tproj/ping.c b/ping.tproj/ping.c
new file mode 100644 (file)
index 0000000..4aad17e
--- /dev/null
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ *                     P I N G . C
+ *
+ * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
+ * measure round-trip-delays and packet loss across network paths.
+ *
+ * Author -
+ *     Mike Muuss
+ *     U. S. Army Ballistic Research Laboratory
+ *     December, 1983
+ *
+ * Status -
+ *     Public Domain.  Distribution Unlimited.
+ * Bugs -
+ *     More statistics could always be gathered.
+ *     This program has to run SUID to ROOT to access the ICMP socket.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_var.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+
+#define        DEFDATALEN      (64 - 8)        /* default data length */
+#define        MAXIPLEN        60
+#define        MAXICMPLEN      76
+#define        MAXPACKET       (65536 - 60 - 8)/* max packet size */
+#define        MAXWAIT         10              /* max seconds to wait for response */
+#define        NROUTES         9               /* number of record route slots */
+
+#define        A(bit)          rcvd_tbl[(bit)>>3]      /* identify byte in array */
+#define        B(bit)          (1 << ((bit) & 0x07))   /* identify bit in byte */
+#define        SET(bit)        (A(bit) |= B(bit))
+#define        CLR(bit)        (A(bit) &= (~B(bit)))
+#define        TST(bit)        (A(bit) & B(bit))
+
+/* various options */
+int options;
+#define        F_FLOOD         0x001
+#define        F_INTERVAL      0x002
+#define        F_NUMERIC       0x004
+#define        F_PINGFILLED    0x008
+#define        F_QUIET         0x010
+#define        F_RROUTE        0x020
+#define        F_SO_DEBUG      0x040
+#define        F_SO_DONTROUTE  0x080
+#define        F_VERBOSE       0x100
+
+/*
+ * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
+ * number of received sequence numbers we can keep track of.  Change 128
+ * to 8192 for complete accuracy...
+ */
+#define        MAX_DUP_CHK     (8 * 128)
+int mx_dup_ck = MAX_DUP_CHK;
+char rcvd_tbl[MAX_DUP_CHK / 8];
+
+struct sockaddr whereto;       /* who to ping */
+int datalen = DEFDATALEN;
+int s;                         /* socket file descriptor */
+u_char outpack[MAXPACKET];
+char BSPACE = '\b';            /* characters written for flood */
+char DOT = '.';
+char *hostname;
+int ident;                     /* process id to identify our packets */
+
+/* counters */
+long npackets;                 /* max packets to transmit */
+long nreceived;                        /* # of packets we got back */
+long nrepeats;                 /* number of duplicates */
+long ntransmitted;             /* sequence # for outbound packets = #sent */
+int interval = 1;              /* interval between packets */
+
+/* timing */
+int timing;                    /* flag to do timing */
+double tmin = 999999999.0;     /* minimum round trip time */
+double tmax = 0.0;             /* maximum round trip time */
+double tsum = 0.0;             /* sum of all times, for doing average */
+
+char *pr_addr();
+void catcher(), finish();
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern int errno, optind;
+       extern char *optarg;
+       struct timeval timeout;
+       struct hostent *hp;
+       struct sockaddr_in *to;
+       struct protoent *proto;
+       register int i;
+       int ch, fdmask, hold, packlen, preload;
+       u_char *datap, *packet;
+       char *target, hnamebuf[MAXHOSTNAMELEN], *malloc();
+#ifdef IP_OPTIONS
+       char rspace[3 + 4 * NROUTES + 1];       /* record route space */
+#endif
+
+       preload = 0;
+       datap = &outpack[8 + sizeof(struct timeval)];
+       while ((ch = getopt(argc, argv, "Rc:dfh:i:l:np:qrs:v")) != EOF)
+               switch(ch) {
+               case 'c':
+                       npackets = atoi(optarg);
+                       if (npackets <= 0) {
+                               (void)fprintf(stderr,
+                                   "ping: bad number of packets to transmit.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'd':
+                       options |= F_SO_DEBUG;
+                       break;
+               case 'f':
+                       if (getuid()) {
+                               (void)fprintf(stderr,
+                                   "ping: %s\n", strerror(EPERM));
+                               exit(1);
+                       }
+                       options |= F_FLOOD;
+                       setbuf(stdout, (char *)NULL);
+                       break;
+               case 'i':               /* wait between sending packets */
+                       interval = atoi(optarg);
+                       if (interval <= 0) {
+                               (void)fprintf(stderr,
+                                   "ping: bad timing interval.\n");
+                               exit(1);
+                       }
+                       options |= F_INTERVAL;
+                       break;
+               case 'l':
+                       if (getuid()) {
+                               (void)fprintf(stderr,
+                                   "ping: %s\n", strerror(EPERM));
+                               exit(1);
+                       }
+                       preload = atoi(optarg);
+                       if (preload < 0) {
+                               (void)fprintf(stderr,
+                                   "ping: bad preload value.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'n':
+                       options |= F_NUMERIC;
+                       break;
+               case 'p':               /* fill buffer with user pattern */
+                       options |= F_PINGFILLED;
+                       fill((char *)datap, optarg);
+                               break;
+               case 'q':
+                       options |= F_QUIET;
+                       break;
+               case 'R':
+                       options |= F_RROUTE;
+                       break;
+               case 'r':
+                       options |= F_SO_DONTROUTE;
+                       break;
+               case 's':               /* size of packet to send */
+                       datalen = atoi(optarg);
+                       if (datalen > MAXPACKET) {
+                               (void)fprintf(stderr,
+                                   "ping: packet size too large.\n");
+                               exit(1);
+                       }
+                       if (datalen <= 0) {
+                               (void)fprintf(stderr,
+                                   "ping: illegal packet size.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'v':
+                       options |= F_VERBOSE;
+                       break;
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 1)
+               usage();
+       target = *argv;
+
+       memset(&whereto, 0, sizeof(struct sockaddr));
+       to = (struct sockaddr_in *)&whereto;
+       to->sin_family = AF_INET;
+       to->sin_addr.s_addr = inet_addr(target);
+       if (to->sin_addr.s_addr != (u_int)-1)
+               hostname = target;
+       else {
+               hp = gethostbyname(target);
+               if (!hp) {
+                       (void)fprintf(stderr,
+                           "ping: unknown host %s\n", target);
+                       exit(1);
+               }
+               to->sin_family = hp->h_addrtype;
+               memmove(&to->sin_addr, hp->h_addr, hp->h_length);
+               (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
+               hostname = hnamebuf;
+       }
+
+       if (options & F_FLOOD && options & F_INTERVAL) {
+               (void)fprintf(stderr,
+                   "ping: -f and -i incompatible options.\n");
+               exit(1);
+       }
+
+       if (datalen >= sizeof(struct timeval))  /* can we time transfer */
+               timing = 1;
+       packlen = datalen + MAXIPLEN + MAXICMPLEN;
+       if (!(packet = (u_char *)malloc((u_int)packlen))) {
+               (void)fprintf(stderr, "ping: out of memory.\n");
+               exit(1);
+       }
+       if (!(options & F_PINGFILLED))
+               for (i = 8; i < datalen; ++i)
+                       *datap++ = i;
+
+       ident = getpid() & 0xFFFF;
+
+       if (!(proto = getprotobyname("icmp"))) {
+               (void)fprintf(stderr, "ping: unknown protocol icmp.\n");
+               exit(1);
+       }
+       if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
+               perror("ping: socket");
+               exit(1);
+       }
+       hold = 1;
+       if (options & F_SO_DEBUG)
+               (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold,
+                   sizeof(hold));
+       if (options & F_SO_DONTROUTE)
+               (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
+                   sizeof(hold));
+
+       /* record route option */
+       if (options & F_RROUTE) {
+#ifdef IP_OPTIONS
+               rspace[IPOPT_OPTVAL] = IPOPT_RR;
+               rspace[IPOPT_OLEN] = sizeof(rspace)-1;
+               rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
+               if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace,
+                   sizeof(rspace)) < 0) {
+                       perror("ping: record route");
+                       exit(1);
+               }
+#else
+               (void)fprintf(stderr,
+                 "ping: record route not available in this implementation.\n");
+               exit(1);
+#endif /* IP_OPTIONS */
+       }
+
+       /*
+        * When pinging the broadcast address, you can get a lot of answers.
+        * Doing something so evil is useful if you are trying to stress the
+        * ethernet, or just want to fill the arp cache to get some stuff for
+        * /etc/ethers.
+        */
+       (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, &packlen, sizeof(packlen));
+
+       if (to->sin_family == AF_INET)
+               (void)printf("PING %s (%s): %d data bytes\n", hostname,
+                   inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr),
+                   datalen);
+       else
+               (void)printf("PING %s: %d data bytes\n", hostname, datalen);
+
+       (void)signal(SIGINT, finish);
+       (void)signal(SIGALRM, catcher);
+
+       while (preload--)               /* fire off them quickies */
+               pinger();
+
+       if ((options & F_FLOOD) == 0)
+               catcher();              /* start things going */
+
+       for (;;) {
+               struct sockaddr_in from;
+               register int cc;
+               int fromlen;
+               sigset_t omask, nmask;
+
+               if (options & F_FLOOD) {
+                       pinger();
+                       timeout.tv_sec = 0;
+                       timeout.tv_usec = 10000;
+                       fdmask = 1 << s;
+                       if (select(s + 1, (fd_set *)&fdmask, (fd_set *)NULL,
+                           (fd_set *)NULL, &timeout) < 1)
+                               continue;
+               }
+               fromlen = sizeof(from);
+               if ((cc = recvfrom(s, (char *)packet, packlen, 0,
+                   (struct sockaddr *)&from, &fromlen)) < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       perror("ping: recvfrom");
+                       continue;
+               }
+               sigemptyset(&nmask);
+               sigaddset(&nmask, SIGALRM);
+               sigprocmask(SIG_BLOCK, &nmask, &omask);
+               pr_pack((char *)packet, cc, &from);
+               sigprocmask(SIG_SETMASK, &omask, NULL);
+               if (npackets && nreceived >= npackets)
+                       break;
+       }
+       finish();
+       /* NOTREACHED */
+}
+
+/*
+ * catcher --
+ *     This routine causes another PING to be transmitted, and then
+ * schedules another SIGALRM for 1 second from now.
+ *
+ * bug --
+ *     Our sense of time will slowly skew (i.e., packets will not be
+ * launched exactly at 1-second intervals).  This does not affect the
+ * quality of the delay and loss statistics.
+ */
+void
+catcher()
+{
+       int waittime;
+
+       pinger();
+       (void)signal(SIGALRM, catcher);
+       if (!npackets || ntransmitted < npackets)
+               alarm((u_int)interval);
+       else {
+               if (nreceived) {
+                       waittime = 2 * tmax / 1000;
+                       if (!waittime)
+                               waittime = 1;
+               } else
+                       waittime = MAXWAIT;
+               (void)signal(SIGALRM, finish);
+               (void)alarm((u_int)waittime);
+       }
+}
+
+/*
+ * pinger --
+ *     Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
+ * will be added on by the kernel.  The ID field is our UNIX process ID,
+ * and the sequence number is an ascending integer.  The first 8 bytes
+ * of the data portion are used to hold a UNIX "timeval" struct in VAX
+ * byte-order, to compute the round-trip time.
+ */
+pinger()
+{
+       register struct icmp *icp;
+       register int cc;
+       int i;
+
+       icp = (struct icmp *)outpack;
+       icp->icmp_type = ICMP_ECHO;
+       icp->icmp_code = 0;
+       icp->icmp_cksum = 0;
+       icp->icmp_seq = ntransmitted++;
+       icp->icmp_id = ident;                   /* ID */
+
+       CLR(icp->icmp_seq % mx_dup_ck);
+
+       if (timing)
+               (void)gettimeofday((struct timeval *)&outpack[8],
+                   (struct timezone *)NULL);
+
+       cc = datalen + 8;                       /* skips ICMP portion */
+
+       /* compute ICMP checksum here */
+       icp->icmp_cksum = in_cksum((u_short *)icp, cc);
+
+       i = sendto(s, (char *)outpack, cc, 0, &whereto,
+           sizeof(struct sockaddr));
+
+       if (i < 0 || i != cc)  {
+               if (i < 0)
+                       perror("ping: sendto");
+               (void)printf("ping: wrote %s %d chars, ret=%d\n",
+                   hostname, cc, i);
+       }
+       if (!(options & F_QUIET) && options & F_FLOOD)
+               (void)write(STDOUT_FILENO, &DOT, 1);
+}
+
+/*
+ * pr_pack --
+ *     Print out the packet, if it came from us.  This logic is necessary
+ * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
+ * which arrive ('tis only fair).  This permits multiple copies of this
+ * program to be run without having intermingled output (or statistics!).
+ */
+pr_pack(buf, cc, from)
+       char *buf;
+       int cc;
+       struct sockaddr_in *from;
+{
+       register struct icmp *icp;
+       register u_long l;
+       register u_int i, j;
+       register u_char *cp,*dp;
+       static int old_rrlen;
+       static char old_rr[MAX_IPOPTLEN];
+       struct ip *ip;
+       struct timeval tv, *tp;
+       double triptime;
+       int hlen, dupflag;
+
+       (void)gettimeofday(&tv, (struct timezone *)NULL);
+
+       /* Check the IP header */
+       ip = (struct ip *)buf;
+       hlen = ip->ip_hl << 2;
+       if (cc < hlen + ICMP_MINLEN) {
+               if (options & F_VERBOSE)
+                       (void)fprintf(stderr,
+                         "ping: packet too short (%d bytes) from %s\n", cc,
+                         inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr));
+               return;
+       }
+
+       /* Now the ICMP part */
+       cc -= hlen;
+       icp = (struct icmp *)(buf + hlen);
+       if (icp->icmp_type == ICMP_ECHOREPLY) {
+               if (icp->icmp_id != ident)
+                       return;                 /* 'Twas not our ECHO */
+               ++nreceived;
+               if (timing) {
+#ifndef icmp_data
+                       tp = (struct timeval *)&icp->icmp_ip;
+#else
+                       tp = (struct timeval *)icp->icmp_data;
+#endif
+                       tvsub(&tv, tp);
+                       triptime = ((double)tv.tv_sec) * 1000.0 +
+                           ((double)tv.tv_usec) / 1000.0;
+                       tsum += triptime;
+                       if (triptime < tmin)
+                               tmin = triptime;
+                       if (triptime > tmax)
+                               tmax = triptime;
+               }
+
+               if (TST(icp->icmp_seq % mx_dup_ck)) {
+                       ++nrepeats;
+                       --nreceived;
+                       dupflag = 1;
+               } else {
+                       SET(icp->icmp_seq % mx_dup_ck);
+                       dupflag = 0;
+               }
+
+               if (options & F_QUIET)
+                       return;
+
+               if (options & F_FLOOD)
+                       (void)write(STDOUT_FILENO, &BSPACE, 1);
+               else {
+                       (void)printf("%d bytes from %s: icmp_seq=%u", cc,
+                          inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
+                          icp->icmp_seq);
+                       (void)printf(" ttl=%d", ip->ip_ttl);
+                       if (timing)
+                               (void)printf(" time=%g ms", triptime);
+                       if (dupflag)
+                               (void)printf(" (DUP!)");
+                       /* check the data */
+                       cp = (u_char*)&icp->icmp_data[8];
+                       dp = &outpack[8 + sizeof(struct timeval)];
+                       for (i = 8; i < datalen; ++i, ++cp, ++dp) {
+                               if (*cp != *dp) {
+       (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
+           i, *dp, *cp);
+                                       cp = (u_char*)&icp->icmp_data[0];
+                                       for (i = 8; i < datalen; ++i, ++cp) {
+                                               if ((i % 32) == 8)
+                                                       (void)printf("\n\t");
+                                               (void)printf("%x ", *cp);
+                                       }
+                                       break;
+                               }
+                       }
+               }
+       } else {
+               /* We've got something other than an ECHOREPLY */
+               if (!(options & F_VERBOSE))
+                       return;
+               (void)printf("%d bytes from %s: ", cc,
+                   pr_addr(from->sin_addr.s_addr));
+               pr_icmph(icp);
+       }
+
+       /* Display any IP options */
+       cp = (u_char *)buf + sizeof(struct ip);
+
+       for (; hlen > (int)sizeof(struct ip); --hlen, ++cp)
+               switch (*cp) {
+               case IPOPT_EOL:
+                       hlen = 0;
+                       break;
+               case IPOPT_LSRR:
+                       (void)printf("\nLSRR: ");
+                       hlen -= 2;
+                       j = *++cp;
+                       ++cp;
+                       if (j > IPOPT_MINOFF)
+                               for (;;) {
+                                       l = *++cp;
+                                       l = (l<<8) + *++cp;
+                                       l = (l<<8) + *++cp;
+                                       l = (l<<8) + *++cp;
+                                       if (l == 0)
+                                               (void)printf("\t0.0.0.0");
+                               else
+                                       (void)printf("\t%s", pr_addr(ntohl(l)));
+                               hlen -= 4;
+                               j -= 4;
+                               if (j <= IPOPT_MINOFF)
+                                       break;
+                               (void)putchar('\n');
+                       }
+                       break;
+               case IPOPT_RR:
+                       j = *++cp;              /* get length */
+                       i = *++cp;              /* and pointer */
+                       hlen -= 2;
+                       if (i > j)
+                               i = j;
+                       i -= IPOPT_MINOFF;
+                       if (i <= 0)
+                               continue;
+                       if (i == old_rrlen
+                           && cp == (u_char *)buf + sizeof(struct ip) + 2
+                           && !memcmp(cp, old_rr, i)
+                           && !(options & F_FLOOD)) {
+                               (void)printf("\t(same route)");
+                               i = ((i + 3) / 4) * 4;
+                               hlen -= i;
+                               cp += i;
+                               break;
+                       }
+                       if (i < MAX_IPOPTLEN) {
+                               old_rrlen = i;
+                               memcpy(old_rr, cp, i);
+                       } else
+                               old_rrlen = 0;
+
+                       (void)printf("\nRR: ");
+                       j = 0;
+                       for (;;) {
+                               l = *++cp;
+                               l = (l<<8) + *++cp;
+                               l = (l<<8) + *++cp;
+                               l = (l<<8) + *++cp;
+                               if (l == 0)
+                                       (void)printf("\t0.0.0.0");
+                               else
+                                       (void)printf("\t%s", pr_addr(ntohl(l)));
+                               hlen -= 4;
+                               i -= 4;
+                               j += 4;
+                               if (i <= 0)
+                                       break;
+                               if (j >= MAX_IPOPTLEN) {
+                                       (void)printf("\t(truncated route)");
+                                       break;
+                               }
+                               (void)putchar('\n');
+                       }
+                       break;
+               case IPOPT_NOP:
+                       (void)printf("\nNOP");
+                       break;
+               default:
+                       (void)printf("\nunknown option %x", *cp);
+                       break;
+               }
+       if (!(options & F_FLOOD)) {
+               (void)putchar('\n');
+               (void)fflush(stdout);
+       }
+}
+
+/*
+ * in_cksum --
+ *     Checksum routine for Internet Protocol family headers (C Version)
+ */
+in_cksum(addr, len)
+       u_short *addr;
+       int len;
+{
+       register int nleft = len;
+       register u_short *w = addr;
+       register int sum = 0;
+       u_short answer = 0;
+
+       /*
+        * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+        * sequential 16 bit words to it, and at the end, fold back all the
+        * carry bits from the top 16 bits into the lower 16 bits.
+        */
+       while (nleft > 1)  {
+               sum += *w++;
+               nleft -= 2;
+       }
+
+       /* mop up an odd byte, if necessary */
+       if (nleft == 1) {
+               *(u_char *)(&answer) = *(u_char *)w ;
+               sum += answer;
+       }
+
+       /* add back carry outs from top 16 bits to low 16 bits */
+       sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
+       sum += (sum >> 16);                     /* add carry */
+       answer = ~sum;                          /* truncate to 16 bits */
+       return(answer);
+}
+
+/*
+ * tvsub --
+ *     Subtract 2 timeval structs:  out = out - in.  Out is assumed to
+ * be >= in.
+ */
+tvsub(out, in)
+       register struct timeval *out, *in;
+{
+       if ((out->tv_usec -= in->tv_usec) < 0) {
+               --out->tv_sec;
+               out->tv_usec += 1000000;
+       }
+       out->tv_sec -= in->tv_sec;
+}
+
+/*
+ * finish --
+ *     Print out statistics, and give up.
+ */
+void
+finish()
+{
+       register int i;
+
+       (void)signal(SIGINT, SIG_IGN);
+       (void)putchar('\n');
+       (void)fflush(stdout);
+       (void)printf("--- %s ping statistics ---\n", hostname);
+       (void)printf("%ld packets transmitted, ", ntransmitted);
+       (void)printf("%ld packets received, ", nreceived);
+       if (nrepeats)
+               (void)printf("+%ld duplicates, ", nrepeats);
+       if (ntransmitted)
+               if (nreceived > ntransmitted)
+                       (void)printf("-- somebody's printing up packets!");
+               else
+                       (void)printf("%d%% packet loss",
+                           (int) (((ntransmitted - nreceived) * 100) /
+                           ntransmitted));
+       (void)putchar('\n');
+       if (nreceived && timing) {
+               /* Only display average to microseconds */
+               i = 1000.0 * tsum / (nreceived + nrepeats);
+               (void)printf("round-trip min/avg/max = %g/%g/%g ms\n",
+                   tmin, ((double)i) / 1000.0, tmax);
+       }
+       exit(0);
+}
+
+#ifdef notdef
+static char *ttab[] = {
+       "Echo Reply",           /* ip + seq + udata */
+       "Dest Unreachable",     /* net, host, proto, port, frag, sr + IP */
+       "Source Quench",        /* IP */
+       "Redirect",             /* redirect type, gateway, + IP  */
+       "Echo",
+       "Time Exceeded",        /* transit, frag reassem + IP */
+       "Parameter Problem",    /* pointer + IP */
+       "Timestamp",            /* id + seq + three timestamps */
+       "Timestamp Reply",      /* " */
+       "Info Request",         /* id + sq */
+       "Info Reply"            /* " */
+};
+#endif
+
+/*
+ * pr_icmph --
+ *     Print a descriptive string about an ICMP header.
+ */
+pr_icmph(icp)
+       struct icmp *icp;
+{
+       switch(icp->icmp_type) {
+       case ICMP_ECHOREPLY:
+               (void)printf("Echo Reply\n");
+               /* XXX ID + Seq + Data */
+               break;
+       case ICMP_UNREACH:
+               switch(icp->icmp_code) {
+               case ICMP_UNREACH_NET:
+                       (void)printf("Destination Net Unreachable\n");
+                       break;
+               case ICMP_UNREACH_HOST:
+                       (void)printf("Destination Host Unreachable\n");
+                       break;
+               case ICMP_UNREACH_PROTOCOL:
+                       (void)printf("Destination Protocol Unreachable\n");
+                       break;
+               case ICMP_UNREACH_PORT:
+                       (void)printf("Destination Port Unreachable\n");
+                       break;
+               case ICMP_UNREACH_NEEDFRAG:
+                       (void)printf("frag needed and DF set\n");
+                       break;
+               case ICMP_UNREACH_SRCFAIL:
+                       (void)printf("Source Route Failed\n");
+                       break;
+               default:
+                       (void)printf("Dest Unreachable, Bad Code: %d\n",
+                           icp->icmp_code);
+                       break;
+               }
+               /* Print returned IP header information */
+#ifndef icmp_data
+               pr_retip(&icp->icmp_ip);
+#else
+               pr_retip((struct ip *)icp->icmp_data);
+#endif
+               break;
+       case ICMP_SOURCEQUENCH:
+               (void)printf("Source Quench\n");
+#ifndef icmp_data
+               pr_retip(&icp->icmp_ip);
+#else
+               pr_retip((struct ip *)icp->icmp_data);
+#endif
+               break;
+       case ICMP_REDIRECT:
+               switch(icp->icmp_code) {
+               case ICMP_REDIRECT_NET:
+                       (void)printf("Redirect Network");
+                       break;
+               case ICMP_REDIRECT_HOST:
+                       (void)printf("Redirect Host");
+                       break;
+               case ICMP_REDIRECT_TOSNET:
+                       (void)printf("Redirect Type of Service and Network");
+                       break;
+               case ICMP_REDIRECT_TOSHOST:
+                       (void)printf("Redirect Type of Service and Host");
+                       break;
+               default:
+                       (void)printf("Redirect, Bad Code: %d", icp->icmp_code);
+                       break;
+               }
+               (void)printf("(New addr: 0x%08lx)\n", icp->icmp_gwaddr.s_addr);
+#ifndef icmp_data
+               pr_retip(&icp->icmp_ip);
+#else
+               pr_retip((struct ip *)icp->icmp_data);
+#endif
+               break;
+       case ICMP_ECHO:
+               (void)printf("Echo Request\n");
+               /* XXX ID + Seq + Data */
+               break;
+       case ICMP_TIMXCEED:
+               switch(icp->icmp_code) {
+               case ICMP_TIMXCEED_INTRANS:
+                       (void)printf("Time to live exceeded\n");
+                       break;
+               case ICMP_TIMXCEED_REASS:
+                       (void)printf("Frag reassembly time exceeded\n");
+                       break;
+               default:
+                       (void)printf("Time exceeded, Bad Code: %d\n",
+                           icp->icmp_code);
+                       break;
+               }
+#ifndef icmp_data
+               pr_retip(&icp->icmp_ip);
+#else
+               pr_retip((struct ip *)icp->icmp_data);
+#endif
+               break;
+       case ICMP_PARAMPROB:
+               (void)printf("Parameter problem: pointer = 0x%02x\n",
+                   icp->icmp_hun.ih_pptr);
+#ifndef icmp_data
+               pr_retip(&icp->icmp_ip);
+#else
+               pr_retip((struct ip *)icp->icmp_data);
+#endif
+               break;
+       case ICMP_TSTAMP:
+               (void)printf("Timestamp\n");
+               /* XXX ID + Seq + 3 timestamps */
+               break;
+       case ICMP_TSTAMPREPLY:
+               (void)printf("Timestamp Reply\n");
+               /* XXX ID + Seq + 3 timestamps */
+               break;
+       case ICMP_IREQ:
+               (void)printf("Information Request\n");
+               /* XXX ID + Seq */
+               break;
+       case ICMP_IREQREPLY:
+               (void)printf("Information Reply\n");
+               /* XXX ID + Seq */
+               break;
+#ifdef ICMP_MASKREQ
+       case ICMP_MASKREQ:
+               (void)printf("Address Mask Request\n");
+               break;
+#endif
+#ifdef ICMP_MASKREPLY
+       case ICMP_MASKREPLY:
+               (void)printf("Address Mask Reply\n");
+               break;
+#endif
+       default:
+               (void)printf("Bad ICMP type: %d\n", icp->icmp_type);
+       }
+}
+
+/*
+ * pr_iph --
+ *     Print an IP header with options.
+ */
+pr_iph(ip)
+       struct ip *ip;
+{
+       int hlen;
+       u_char *cp;
+
+       hlen = ip->ip_hl << 2;
+       cp = (u_char *)ip + 20;         /* point to options */
+
+       (void)printf("Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst Data\n");
+       (void)printf(" %1x  %1x  %02x %04x %04x",
+           ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id);
+       (void)printf("   %1x %04x", ((ip->ip_off) & 0xe000) >> 13,
+           (ip->ip_off) & 0x1fff);
+       (void)printf("  %02x  %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum);
+       (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
+       (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
+       /* dump and option bytes */
+       while (hlen-- > 20) {
+               (void)printf("%02x", *cp++);
+       }
+       (void)putchar('\n');
+}
+
+/*
+ * pr_addr --
+ *     Return an ascii host address as a dotted quad and optionally with
+ * a hostname.
+ */
+char *
+pr_addr(l)
+       u_long l;
+{
+       struct hostent *hp;
+       static char buf[80];
+
+       if ((options & F_NUMERIC) ||
+           !(hp = gethostbyaddr((char *)&l, 4, AF_INET)))
+               (void)sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)&l));
+       else
+               (void)sprintf(buf, "%s (%s)", hp->h_name,
+                   inet_ntoa(*(struct in_addr *)&l));
+       return(buf);
+}
+
+/*
+ * pr_retip --
+ *     Dump some info on a returned (via ICMP) IP packet.
+ */
+pr_retip(ip)
+       struct ip *ip;
+{
+       int hlen;
+       u_char *cp;
+
+       pr_iph(ip);
+       hlen = ip->ip_hl << 2;
+       cp = (u_char *)ip + hlen;
+
+       if (ip->ip_p == 6)
+               (void)printf("TCP: from port %u, to port %u (decimal)\n",
+                   (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
+       else if (ip->ip_p == 17)
+               (void)printf("UDP: from port %u, to port %u (decimal)\n",
+                       (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
+}
+
+fill(bp, patp)
+       char *bp, *patp;
+{
+       register int ii, jj, kk;
+       int pat[16];
+       char *cp;
+
+       for (cp = patp; *cp; cp++)
+               if (!isxdigit(*cp)) {
+                       (void)fprintf(stderr,
+                           "ping: patterns must be specified as hex digits.\n");
+                       exit(1);
+               }
+       ii = sscanf(patp,
+           "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+           &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
+           &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
+           &pat[13], &pat[14], &pat[15]);
+
+       if (ii > 0)
+               for (kk = 0;
+                   kk <= MAXPACKET - (8 + sizeof(struct timeval) + ii);
+                   kk += ii)
+                       for (jj = 0; jj < ii; ++jj)
+                               bp[jj + kk] = pat[jj];
+       if (!(options & F_QUIET)) {
+               (void)printf("PATTERN: 0x");
+               for (jj = 0; jj < ii; ++jj)
+                       (void)printf("%02x", bp[jj] & 0xFF);
+               (void)printf("\n");
+       }
+}
+
+usage()
+{
+       (void)fprintf(stderr,
+           "usage: ping [-Rdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] host\n");
+       exit(1);
+}
diff --git a/portmap.tproj/Makefile b/portmap.tproj/Makefile
new file mode 100644 (file)
index 0000000..5a91e65
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = portmap
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = portmap.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble portmap.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/portmap.tproj/Makefile.postamble b/portmap.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..f5c79e2
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
diff --git a/portmap.tproj/Makefile.preamble b/portmap.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2c9003c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/portmap.tproj/PB.project b/portmap.tproj/PB.project
new file mode 100644 (file)
index 0000000..b9275bb
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (portmap.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, portmap.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = portmap; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/portmap.tproj/portmap.8 b/portmap.tproj/portmap.8
new file mode 100644 (file)
index 0000000..a651f5f
--- /dev/null
@@ -0,0 +1,110 @@
+.\" Copyright (c) 1987 Sun Microsystems
+.\" Copyright (c) 1990, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)portmap.8  8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt PORTMAP 8
+.Os BSD 4.3
+.Sh NAME
+.Nm portmap
+.Nd
+.Tn DARPA
+port to
+.Tn RPC
+program number mapper
+.Sh SYNOPSIS
+.Nm portmap
+.Op Fl d
+.Sh DESCRIPTION
+.Nm Portmap
+is a server that converts
+.Tn RPC
+program numbers into
+.Tn DARPA
+protocol port numbers.
+It must be running in order to make
+.Tn RPC
+calls.
+.Pp
+When an
+.Tn RPC
+server is started, it will tell
+.Nm portmap
+what port number it is listening to, and what
+.Tn RPC
+program numbers it is prepared to serve.
+When a client wishes to make an
+.Tn RPC
+call to a given program number,
+it will first contact
+.Nm portmap
+on the server machine to determine
+the port number where
+.Tn RPC
+packets should be sent.
+.Pp
+.Nm Portmap
+must be started before any
+.Tn RPC
+servers are invoked.
+.Pp
+Normally
+.Nm portmap
+forks and dissociates itself from the terminal
+like any other daemon.
+.Nm Portmap
+then logs errors using
+.Xr syslog 3 .
+.Pp
+Option available:
+.Bl -tag -width Ds
+.It Fl d
+(debug) prevents
+.Nm portmap
+from running as a daemon,
+and causes errors and debugging information
+to be printed to the standard error output.
+.El
+.Sh SEE ALSO
+.Xr inetd.conf 5 ,
+.Xr rpcinfo 8 ,
+.Xr inetd 8
+.Sh BUGS
+If
+.Nm portmap
+crashes, all servers must be restarted.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3
diff --git a/portmap.tproj/portmap.c b/portmap.tproj/portmap.c
new file mode 100644 (file)
index 0000000..8a6c53c
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)portmap.c  8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+@(#)portmap.c  2.3 88/08/11 4.0 RPCSRC
+static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
+*/
+
+/*
+ * portmap.c, Implements the program,version to port number mapping for
+ * rpc.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <netinfo/nibind_prot.h>
+
+#define NETINFO_TAG_NETWORK "network"
+#define NETINFO_NETWORK_DIR_PATH "/var/db/netinfo/network.nidb"
+#define NETINFO_STAT_LATENCY 30
+
+static int have_tag_network = 0;
+static struct timeval last_network_stat = {0, 0};
+
+void reg_service();
+void reap();
+static void callit();
+struct pmaplist *pmaplist;
+int debugging = 0;
+extern int errno;
+extern int svc_maxfd;
+
+extern int get_myaddress();
+
+static void
+portmap_svc_run()
+{
+       fd_set readfds;
+       int status;
+       
+       for (;;)
+       {
+               readfds = svc_fdset;
+               switch ((status = select(svc_maxfd+1, &readfds, NULL, NULL, NULL)))
+               {
+                       case -1:
+                               if (errno == EINTR) continue;
+
+                               if ((errno == EFAULT) || (errno == EINVAL))
+                               {
+                                       syslog(LOG_ERR, "aborting - select error %d (%s)",
+                                               errno, strerror(errno));
+                                       return;
+                               }
+
+                               syslog(LOG_NOTICE, "ignoring select error %d (%s)",
+                                       errno, strerror(errno));
+                               continue;
+
+                       case 0:
+                               continue;
+
+                       default:
+                               svc_getreqset(&readfds);
+               }
+       }
+}
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       SVCXPRT *xprt;
+       int sock, c;
+       struct sockaddr_in addr;
+       int len = sizeof(struct sockaddr_in);
+       register struct pmaplist *pml;
+
+       while ((c = getopt(argc, argv, "d")) != EOF) {
+               switch (c) {
+
+               case 'd':
+                       debugging = 1;
+                       break;
+
+               default:
+                       (void) fprintf(stderr, "usage: %s [-d]\n", argv[0]);
+                       exit(1);
+               }
+       }
+
+       if (!debugging && daemon(0, 0)) {
+               (void) fprintf(stderr, "portmap: fork: %s", strerror(errno));
+               exit(1);
+       }
+
+       openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID,
+           LOG_DAEMON);
+
+       if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+               syslog(LOG_ERR, "cannot create udp socket: %m");
+               exit(1);
+       }
+
+       addr.sin_addr.s_addr = 0;
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(PMAPPORT);
+       if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+               syslog(LOG_ERR, "cannot bind udp: %m");
+               exit(1);
+       }
+
+       if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
+               syslog(LOG_ERR, "couldn't do udp_create");
+               exit(1);
+       }
+       /* make an entry for ourself */
+       pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
+       pml->pml_next = 0;
+       pml->pml_map.pm_prog = PMAPPROG;
+       pml->pml_map.pm_vers = PMAPVERS;
+       pml->pml_map.pm_prot = IPPROTO_UDP;
+       pml->pml_map.pm_port = PMAPPORT;
+       pmaplist = pml;
+
+       if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+               syslog(LOG_ERR, "cannot create tcp socket: %m");
+               exit(1);
+       }
+       if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+               syslog(LOG_ERR, "cannot bind udp: %m");
+               exit(1);
+       }
+       if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
+           == (SVCXPRT *)NULL) {
+               syslog(LOG_ERR, "couldn't do tcp_create");
+               exit(1);
+       }
+       /* make an entry for ourself */
+       pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
+       pml->pml_map.pm_prog = PMAPPROG;
+       pml->pml_map.pm_vers = PMAPVERS;
+       pml->pml_map.pm_prot = IPPROTO_TCP;
+       pml->pml_map.pm_port = PMAPPORT;
+       pml->pml_next = pmaplist;
+       pmaplist = pml;
+
+       (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
+
+       /* initialize "network.nidb" timer */
+       gettimeofday(&last_network_stat, NULL);
+
+       (void)signal(SIGCHLD, reap);
+       portmap_svc_run();
+       syslog(LOG_ERR, "run_svc returned unexpectedly");
+       abort();
+}
+
+#ifndef lint
+/* need to override perror calls in rpc library */
+__private_extern__
+void
+perror(what)
+       const char *what;
+{
+
+       syslog(LOG_ERR, "%s: %m", what);
+}
+#endif
+
+static struct pmaplist *
+find_service(prog, vers, prot)
+       u_long prog, vers, prot;
+{
+       register struct pmaplist *hit = NULL;
+       register struct pmaplist *pml;
+
+       for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
+               if ((pml->pml_map.pm_prog != prog) ||
+                       (pml->pml_map.pm_prot != prot))
+                       continue;
+               hit = pml;
+               if (pml->pml_map.pm_vers == vers)
+                   break;
+       }
+       return (hit);
+}
+
+/* 
+ * 1 OK, 0 not
+ */
+void
+reg_service(rqstp, xprt)
+       struct svc_req *rqstp;
+       SVCXPRT *xprt;
+{
+       struct pmap reg;
+       struct pmaplist *pml, *prevpml, *fnd;
+       int ans, port;
+       caddr_t t;
+       
+       if (debugging)
+               (void) fprintf(stderr, "server: about do a switch\n");
+       switch (rqstp->rq_proc) {
+
+       case PMAPPROC_NULL:
+               /*
+                * Null proc call
+                */
+               if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) {
+                       abort();
+               }
+               break;
+
+       case PMAPPROC_SET:
+               /*
+                * Set a program,version to port mapping
+                */
+               if (!svc_getargs(xprt, xdr_pmap, &reg))
+                       svcerr_decode(xprt);
+               else {
+                       /*
+                        * check to see if already used
+                        * find_service returns a hit even if
+                        * the versions don't match, so check for it
+                        */
+                       fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+                       if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
+                               if (fnd->pml_map.pm_port == reg.pm_port) {
+                                       ans = 1;
+                                       goto done;
+                               }
+                               else {
+                                       ans = 0;
+                                       goto done;
+                               }
+                       } else {
+                               /* 
+                                * add to END of list
+                                */
+                               pml = (struct pmaplist *)
+                                   malloc((u_int)sizeof(struct pmaplist));
+                               pml->pml_map = reg;
+                               pml->pml_next = 0;
+                               if (pmaplist == 0) {
+                                       pmaplist = pml;
+                               } else {
+                                       for (fnd= pmaplist; fnd->pml_next != 0;
+                                           fnd = fnd->pml_next);
+                                       fnd->pml_next = pml;
+                               }
+                               ans = 1;
+                       }
+               done:
+                       if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
+                           debugging) {
+                               (void) fprintf(stderr, "svc_sendreply\n");
+                               abort();
+                       }
+               }
+               break;
+
+       case PMAPPROC_UNSET:
+               /*
+                * Remove a program,version to port mapping.
+                */
+               if (!svc_getargs(xprt, xdr_pmap, &reg))
+                       svcerr_decode(xprt);
+               else {
+                       ans = 0;
+                       for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
+                               if ((pml->pml_map.pm_prog != reg.pm_prog) ||
+                                       (pml->pml_map.pm_vers != reg.pm_vers)) {
+                                       /* both pml & prevpml move forwards */
+                                       prevpml = pml;
+                                       pml = pml->pml_next;
+                                       continue;
+                               }
+                               /* found it; pml moves forward, prevpml stays */
+                               ans = 1;
+                               t = (caddr_t)pml;
+                               pml = pml->pml_next;
+                               if (prevpml == NULL)
+                                       pmaplist = pml;
+                               else
+                                       prevpml->pml_next = pml;
+                               free(t);
+                       }
+                       if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
+                           debugging) {
+                               (void) fprintf(stderr, "svc_sendreply\n");
+                               abort();
+                       }
+               }
+               break;
+
+       case PMAPPROC_GETPORT:
+               /*
+                * Lookup the mapping for a program,version and return its port
+                */
+               if (!svc_getargs(xprt, xdr_pmap, &reg))
+                       svcerr_decode(xprt);
+               else {
+                       fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+                       if (fnd)
+                               port = fnd->pml_map.pm_port;
+                       else
+                               port = 0;
+                       if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
+                           debugging) {
+                               (void) fprintf(stderr, "svc_sendreply\n");
+                               abort();
+                       }
+               }
+               break;
+
+       case PMAPPROC_DUMP:
+               /*
+                * Return the current set of mapped program,version
+                */
+               if (!svc_getargs(xprt, xdr_void, NULL))
+                       svcerr_decode(xprt);
+               else {
+                       if ((!svc_sendreply(xprt, xdr_pmaplist,
+                           (caddr_t)&pmaplist)) && debugging) {
+                               (void) fprintf(stderr, "svc_sendreply\n");
+                               abort();
+                       }
+               }
+               break;
+
+       case PMAPPROC_CALLIT:
+               /*
+                * Calls a procedure on the local machine.  If the requested
+                * procedure is not registered this procedure does not return
+                * error information!!
+                * This procedure is only supported on rpc/udp and calls via 
+                * rpc/udp.  It passes null authentication parameters.
+                */
+               callit(rqstp, xprt);
+               break;
+
+       default:
+               svcerr_noproc(xprt);
+               break;
+       }
+}
+
+
+/*
+ * Stuff for the rmtcall service
+ */
+#define ARGSIZE 9000
+
+struct encap_parms {
+       u_long arglen;
+       char *args;
+};
+
+static bool_t
+xdr_encap_parms(xdrs, epp)
+       XDR *xdrs;
+       struct encap_parms *epp;
+{
+       return (xdr_bytes(xdrs, &(epp->args), (int *)&(epp->arglen), ARGSIZE));
+}
+
+struct rmtcallargs {
+       u_long  rmt_prog;
+       u_long  rmt_vers;
+       u_long  rmt_port;
+       u_long  rmt_proc;
+       struct encap_parms rmt_args;
+};
+
+static bool_t
+xdr_rmtcall_args(xdrs, cap)
+       register XDR *xdrs;
+       register struct rmtcallargs *cap;
+{
+
+       /* does not get a port number */
+       if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
+           xdr_u_long(xdrs, &(cap->rmt_vers)) &&
+           xdr_u_long(xdrs, &(cap->rmt_proc))) {
+               return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+       }
+       return (FALSE);
+}
+
+static bool_t
+xdr_rmtcall_result(xdrs, cap)
+       register XDR *xdrs;
+       register struct rmtcallargs *cap;
+{
+       if (xdr_u_long(xdrs, &(cap->rmt_port)))
+               return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+       return (FALSE);
+}
+
+/*
+ * only worries about the struct encap_parms part of struct rmtcallargs.
+ * The arglen must already be set!!
+ */
+static bool_t
+xdr_opaque_parms(xdrs, cap)
+       XDR *xdrs;
+       struct rmtcallargs *cap;
+{
+
+       return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
+}
+
+/*
+ * This routine finds and sets the length of incoming opaque paraters
+ * and then calls xdr_opaque_parms.
+ */
+static bool_t
+xdr_len_opaque_parms(xdrs, cap)
+       register XDR *xdrs;
+       struct rmtcallargs *cap;
+{
+       register u_int beginpos, lowpos, highpos, currpos, pos;
+
+       beginpos = lowpos = pos = xdr_getpos(xdrs);
+       highpos = lowpos + ARGSIZE;
+       while ((int)(highpos - lowpos) >= 0) {
+               currpos = (lowpos + highpos) / 2;
+               if (xdr_setpos(xdrs, currpos)) {
+                       pos = currpos;
+                       lowpos = currpos + 1;
+               } else {
+                       highpos = currpos - 1;
+               }
+       }
+       xdr_setpos(xdrs, beginpos);
+       cap->rmt_args.arglen = pos - beginpos;
+       return (xdr_opaque_parms(xdrs, cap));
+}
+
+/*
+ * Call a remote procedure service
+ * This procedure is very quiet when things go wrong.
+ * The proc is written to support broadcast rpc.  In the broadcast case,
+ * a machine should shut-up instead of complain, less the requestor be
+ * overrun with complaints at the expense of not hearing a valid reply ...
+ *
+ * This now forks so that the program & process that it calls can call 
+ * back to the portmapper.
+ */
+static void
+callit(rqstp, xprt)
+       struct svc_req *rqstp;
+       SVCXPRT *xprt;
+{
+       struct rmtcallargs a;
+       struct pmaplist *pml;
+       u_short port;
+       struct sockaddr_in me;
+       int pid, so = -1;
+       CLIENT *client;
+       struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
+       struct timeval timeout;
+       char buf[ARGSIZE];
+       char tag[MAXPATHLEN];
+       int off, taglen;
+       unsigned int delta;
+       struct stat sb;
+       struct timeval now;
+
+       timeout.tv_sec = 5;
+       timeout.tv_usec = 0;
+       a.rmt_args.args = buf;
+       if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
+               return;
+
+       /*
+        * Drop NIBIND_BIND calls for the parent tag "network" if the database 
+        * doesn't exist.  This prevents excessive fork() calls.
+        */
+       if ((have_tag_network == 0) && (a.rmt_prog == NIBIND_PROG) && (a.rmt_proc == NIBIND_BIND))
+       {
+               /* Skip sender address and child tag */
+               memmove(&taglen, a.rmt_args.args + 4, 4);
+               taglen = ntohl(taglen);
+               off = 8 + (((taglen + 3) / 4) * 4);
+
+               /* Get parent tag */
+               memmove(&taglen, a.rmt_args.args + off, 4);
+               taglen = ntohl(taglen);
+               if (taglen >= MAXPATHLEN) return;
+
+               off += 4;
+               memmove(tag, a.rmt_args.args + off, taglen);
+               tag[taglen] = '\0';
+
+               /*
+                * If there was no network.nidb a few seconds ago, drop the requset.
+                */
+               if (!strcmp(tag, NETINFO_TAG_NETWORK))
+               {
+                       gettimeofday(&now, NULL);
+                       delta = now.tv_sec - last_network_stat.tv_sec;
+                       if (delta < NETINFO_STAT_LATENCY) return;
+
+                       if (stat(NETINFO_NETWORK_DIR_PATH, &sb) < 0)
+                       {
+                               last_network_stat = now;
+                               return;
+                       }
+
+                       have_tag_network = 1;
+               }
+       }
+
+       if ((pml = find_service(a.rmt_prog, a.rmt_vers,
+           (u_long)IPPROTO_UDP)) == NULL)
+               return;
+       /*
+        * fork a child to do the work.  Parent immediately returns.
+        * Child exits upon completion.
+        */
+       if ((pid = fork()) != 0) {
+               if (pid < 0)
+                       syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m",
+                           a.rmt_prog);
+               return;
+       }
+       port = pml->pml_map.pm_port;
+       get_myaddress(&me);
+       me.sin_port = htons(port);
+       client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so);
+       if (client != (CLIENT *)NULL) {
+               if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
+                       client->cl_auth = authunix_create(au->aup_machname,
+                          au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
+               }
+               a.rmt_port = (u_long)port;
+               if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
+                   xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
+                       svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a);
+               }
+               AUTH_DESTROY(client->cl_auth);
+               clnt_destroy(client);
+       }
+       (void)close(so);
+       exit(0);
+}
+
+void
+reap()
+{
+       while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
+}
diff --git a/rarpd.tproj/Makefile b/rarpd.tproj/Makefile
new file mode 100644 (file)
index 0000000..34700cd
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rarpd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = rarpd.c
+
+OTHERSRCS = Makefile.dist Makefile.preamble rarpd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS = -I.
+NEXTSTEP_PB_CFLAGS = -DTFTP_DIR=\"/tftpboot\"
+WINDOWS_PB_CFLAGS = -DTFTP_DIR=\"/tftpboot\"
+PDO_UNIX_PB_CFLAGS = -DTFTP_DIR=\"/tftpboot\"
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rarpd.tproj/Makefile.dist b/rarpd.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..2c02ca5
--- /dev/null
@@ -0,0 +1,10 @@
+# @(#) $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:57:59 wsanchez Exp $
+
+PROG=  rarpd
+SRCS=  rarpd.c
+
+CFLAGS+=-I${.CURDIR} -DTFTP_DIR=\"/tftpboot\"
+
+MAN8=  rarpd.0
+
+.include <bsd.prog.mk>
diff --git a/rarpd.tproj/Makefile.preamble b/rarpd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/rarpd.tproj/PB.project b/rarpd.tproj/PB.project
new file mode 100644 (file)
index 0000000..8c54327
--- /dev/null
@@ -0,0 +1,37 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        HEADERSEARCH = (.); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (rarpd.c); 
+        OTHER_SOURCES = (Makefile.dist, Makefile.preamble, rarpd.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = "-DTFTP_DIR=\\\"/tftpboot\\\""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DTFTP_DIR=\\\"/tftpboot\\\""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rarpd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = "-DTFTP_DIR=\\\"/tftpboot\\\""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rarpd.tproj/rarpd.8 b/rarpd.tproj/rarpd.8
new file mode 100644 (file)
index 0000000..f090c47
--- /dev/null
@@ -0,0 +1,92 @@
+.\"
+.\" Copyright (c) 1988-1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\" @(#) $Id: rarpd.8,v 1.1.1.1 1999/05/02 03:57:59 wsanchez Exp $
+.\"
+.Dd October 26, 1990
+.Dt RARPD 8
+.Sh NAME
+.Nm rarpd 
+.Nd Reverse ARP Daemon
+.Sh SYNOPSIS
+.Nm rarpd 
+.Op Fl adf
+.Op Ar interface
+.Sh DESCRIPTION
+.Nm Rarpd
+services Reverse ARP requests on the Ethernet connected to
+.Ar interface.
+Upon receiving a request, 
+.Nm rarpd
+maps the target hardware address to an IP address via its name, which 
+must be present in both the
+.Xr ethers 5
+and 
+.Xr hosts 5
+databases.
+If a host does not exist in both databases, the translation cannot
+proceed and a reply will not be sent.
+.Pp
+Additionally, a request is honored only if the server
+(i.e., the host that rarpd is running on)
+can "boot" the target; that is, if the directory 
+.Pa /tftpboot/ Ns Em ipaddr
+exists, where 
+.Rm ipaddr
+is the target IP address.
+.Pp
+In normal operation, 
+.Nm rarpd
+forks a copy of itself and runs in
+the background.  Anomalies and errors are reported via 
+.Xr syslog 3 .
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl a
+Listen on all the Ethernets attached to the system.
+If 
+.Sq Fl a 
+is omitted, an interface must be specified.
+.It Fl d
+Run in debug mode, with all the output to stderr.
+This option implies the 
+.Fl f
+option.
+.It Fl f
+Run in the foreground.
+.El
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /etc/ethers
+.It Pa /etc/hosts
+.It Pa /tftpboot
+.El
+.Sh SEE ALSO
+.Xr bpf 4 ,
+.Rs 
+.%R A Reverse Address  Resolution Protocol
+.%N RFC 903
+.%A Finlayson, R.
+.%A Mann, T.
+.%A Mogul, J.C.
+.%A Theimer, M.
+.Re
+.Sh AUTHORS
+Craig Leres (leres@ee.lbl.gov) and Steven McCanne (mccanne@ee.lbl.gov).
+Lawrence Berkeley Laboratory, University of California, Berkeley, CA.
diff --git a/rarpd.tproj/rarpd.c b/rarpd.tproj/rarpd.c
new file mode 100644 (file)
index 0000000..890be78
--- /dev/null
@@ -0,0 +1,831 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+char    copyright[] =
+"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif                         /* not lint */
+
+#ifndef lint
+static char rcsid[] =
+"@(#) $Id: rarpd.c,v 1.1.1.1 1999/05/02 03:57:59 wsanchez Exp $";
+#endif
+
+
+/*
+ * rarpd - Reverse ARP Daemon
+ *
+ * Usage:      rarpd -a [ -d -f ]
+ *             rarpd [ -d -f ] interface
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <net/bpf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <dirent.h>
+
+#define FATAL          1       /* fatal error occurred */
+#define NONFATAL       0       /* non fatal error occurred */
+
+/*
+ * The structure for each interface.
+ */
+struct if_info {
+       int     ii_fd;          /* BPF file descriptor */
+       u_char  ii_eaddr[6];    /* Ethernet address of this interface */
+       u_long  ii_ipaddr;      /* IP address of this interface */
+       u_long  ii_netmask;     /* subnet or net mask */
+       struct if_info *ii_next;
+};
+/*
+ * The list of all interfaces that are being listened to.  rarp_loop()
+ * "selects" on the descriptors in this list.
+ */
+struct if_info *iflist;
+
+int    rarp_open     __P((char *));
+int    rarp_bootable __P((u_long));
+void   init_one      __P((char *));
+void   init_all      __P((void));
+void   rarp_loop     __P((void));
+void   lookup_eaddr  __P((char *, u_char *));
+void   lookup_ipaddr __P((char *, u_long *, u_long *));
+void   usage         __P((void));
+void   rarp_process  __P((struct if_info *, u_char *));
+void   rarp_reply    __P((struct if_info *, struct ether_header *, u_long));
+void   update_arptab __P((u_char *, u_long));
+void   err           __P((int, const char *,...));
+void   debug         __P((const char *,...));
+u_long ipaddrtonetmask __P((u_long));
+
+int     aflag = 0;             /* listen on "all" interfaces  */
+int     dflag = 0;             /* print debugging messages */
+int     fflag = 0;             /* don't fork */
+
+void
+main(argc, argv)
+       int     argc;
+       char  **argv;
+{
+       int     op, pid, devnull, f;
+       char   *ifname, *hostname, *name;
+
+       extern char *optarg;
+       extern int optind, opterr;
+
+       if (name = strrchr(argv[0], '/'))
+               ++name;
+       else
+               name = argv[0];
+       if (*name == '-')
+               ++name;
+
+       /* All error reporting is done through syslogs. */
+       openlog(name, LOG_PID | LOG_CONS, LOG_DAEMON);
+
+       opterr = 0;
+       while ((op = getopt(argc, argv, "adf")) != EOF) {
+               switch (op) {
+               case 'a':
+                       ++aflag;
+                       break;
+
+               case 'd':
+                       ++dflag;
+                       break;
+
+               case 'f':
+                       ++fflag;
+                       break;
+
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+       ifname = argv[optind++];
+       hostname = ifname ? argv[optind] : 0;
+       if ((aflag && ifname) || (!aflag && ifname == 0))
+               usage();
+
+       if (aflag)
+               init_all();
+       else
+               init_one(ifname);
+
+       if ((!fflag) && (!dflag)) {
+               pid = fork();
+               if (pid > 0)
+                       /* Parent exits, leaving child in background. */
+                       exit(0);
+               else
+                       if (pid == -1) {
+                               err(FATAL, "cannot fork");
+                               /* NOTREACHED */
+                       }
+               /* Fade into the background */
+               f = open("/dev/tty", O_RDWR);
+               if (f >= 0) {
+                       if (ioctl(f, TIOCNOTTY, 0) < 0) {
+                               err(FATAL, "TIOCNOTTY: %s", strerror(errno));
+                               /* NOTREACHED */
+                       }
+                       (void) close(f);
+               }
+               (void) chdir("/");
+               (void) setpgrp(0, getpid());
+               devnull = open("/dev/null", O_RDWR);
+               if (devnull >= 0) {
+                       (void) dup2(devnull, 0);
+                       (void) dup2(devnull, 1);
+                       (void) dup2(devnull, 2);
+                       if (devnull > 2)
+                               (void) close(devnull);
+               }
+       }
+       rarp_loop();
+}
+/*
+ * Add 'ifname' to the interface list.  Lookup its IP address and network
+ * mask and Ethernet address, and open a BPF file for it.
+ */
+void
+init_one(ifname)
+       char   *ifname;
+{
+       struct if_info *p;
+
+       p = (struct if_info *)malloc(sizeof(*p));
+       if (p == 0) {
+               err(FATAL, "malloc: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       p->ii_next = iflist;
+       iflist = p;
+
+       p->ii_fd = rarp_open(ifname);
+       lookup_eaddr(ifname, p->ii_eaddr);
+       lookup_ipaddr(ifname, &p->ii_ipaddr, &p->ii_netmask);
+}
+/*
+ * Initialize all "candidate" interfaces that are in the system
+ * configuration list.  A "candidate" is up, not loopback and not
+ * point to point.
+ */
+void
+init_all()
+{
+       char inbuf[8192];
+       struct ifconf ifc;
+       struct ifreq *ifr;
+       int fd;
+       int i, len;
+
+       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               err(FATAL, "socket: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+
+       ifc.ifc_len = sizeof(inbuf);
+       ifc.ifc_buf = inbuf;
+       if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 ||
+           ifc.ifc_len < sizeof(struct ifreq)) {
+               err(FATAL, "init_all: SIOCGIFCONF: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       ifr = ifc.ifc_req;
+       for (i = 0; i < ifc.ifc_len;
+            i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
+               len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
+               if (ioctl(fd, SIOCGIFFLAGS, (caddr_t)ifr) < 0) {
+                       err(FATAL, "init_all: SIOCGIFFLAGS: %s",
+                           strerror(errno));
+                       /* NOTREACHED */
+               }
+               if ((ifr->ifr_flags &
+                   (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
+                       continue;
+               init_one(ifr->ifr_name);
+       }
+       (void) close(fd);
+}
+
+void
+usage()
+{
+       (void) fprintf(stderr, "usage: rarpd -a [ -d -f ]\n");
+       (void) fprintf(stderr, "       rarpd [ -d -f ] interface\n");
+       exit(1);
+}
+
+static int
+bpf_open()
+{
+       int     fd;
+       int     n = 0;
+       char    device[sizeof "/dev/bpf000"];
+
+       /* Go through all the minors and find one that isn't in use. */
+       do {
+               (void) sprintf(device, "/dev/bpf%d", n++);
+               fd = open(device, O_RDWR);
+       } while (fd < 0 && errno == EBUSY);
+
+       if (fd < 0) {
+               err(FATAL, "%s: %s", device, strerror(errno));
+               /* NOTREACHED */
+       }
+       return fd;
+}
+/*
+ * Open a BPF file and attach it to the interface named 'device'.
+ * Set immediate mode, and set a filter that accepts only RARP requests.
+ */
+int
+rarp_open(device)
+       char   *device;
+{
+       int     fd;
+       struct ifreq ifr;
+       u_int   dlt;
+       int     immediate;
+
+       static struct bpf_insn insns[] = {
+               BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12),
+               BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_REVARP, 0, 3),
+               BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20),
+               BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ARPOP_REVREQUEST, 0, 1),
+               BPF_STMT(BPF_RET | BPF_K, sizeof(struct ether_arp) +
+                   sizeof(struct ether_header)),
+               BPF_STMT(BPF_RET | BPF_K, 0),
+       };
+       static struct bpf_program filter = {
+               sizeof insns / sizeof(insns[0]),
+               insns
+       };
+
+       fd = bpf_open();
+
+       /* Set immediate mode so packets are processed as they arrive. */
+       immediate = 1;
+       if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
+               err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       (void) strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
+       if (ioctl(fd, BIOCSETIF, (caddr_t) & ifr) < 0) {
+               err(FATAL, "BIOCSETIF: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       /* Check that the data link layer is an Ethernet; this code won't work
+        * with anything else. */
+       if (ioctl(fd, BIOCGDLT, (caddr_t) & dlt) < 0) {
+               err(FATAL, "BIOCGDLT: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       if (dlt != DLT_EN10MB) {
+               err(FATAL, "%s is not an ethernet", device);
+               /* NOTREACHED */
+       }
+       /* Set filter program. */
+       if (ioctl(fd, BIOCSETF, (caddr_t) & filter) < 0) {
+               err(FATAL, "BIOCSETF: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       return fd;
+}
+/*
+ * Perform various sanity checks on the RARP request packet.  Return
+ * false on failure and log the reason.
+ */
+static int
+rarp_check(p, len)
+       u_char *p;
+       int     len;
+{
+       struct ether_header *ep = (struct ether_header *) p;
+       struct ether_arp *ap = (struct ether_arp *) (p + sizeof(*ep));
+
+       (void) debug("got a packet");
+
+       if (len < sizeof(*ep) + sizeof(*ap)) {
+               err(NONFATAL, "truncated request");
+               return 0;
+       }
+       /* XXX This test might be better off broken out... */
+       if (ntohs (ep->ether_type) != ETHERTYPE_REVARP ||
+           ntohs (ap->arp_hrd) != ARPHRD_ETHER ||
+           ntohs (ap->arp_op) != ARPOP_REVREQUEST ||
+           ntohs (ap->arp_pro) != ETHERTYPE_IP ||
+           ap->arp_hln != 6 || ap->arp_pln != 4) {
+               err(NONFATAL, "request fails sanity check");
+               return 0;
+       }
+       if (bcmp((char *) &ep->ether_shost, (char *) &ap->arp_sha, 6) != 0) {
+               err(NONFATAL, "ether/arp sender address mismatch");
+               return 0;
+       }
+       if (bcmp((char *) &ap->arp_sha, (char *) &ap->arp_tha, 6) != 0) {
+               err(NONFATAL, "ether/arp target address mismatch");
+               return 0;
+       }
+       return 1;
+}
+
+/*
+ * Loop indefinitely listening for RARP requests on the
+ * interfaces in 'iflist'.
+ */
+void
+rarp_loop()
+{
+       u_char *buf, *bp, *ep;
+       int     cc, fd;
+       fd_set  fds, listeners;
+       int     bufsize, maxfd = 0;
+       struct if_info *ii;
+
+       if (iflist == 0) {
+               err(FATAL, "no interfaces");
+               /* NOTREACHED */
+       }
+       if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) {
+               err(FATAL, "BIOCGBLEN: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       buf = (u_char *) malloc((unsigned) bufsize);
+       if (buf == 0) {
+               err(FATAL, "malloc: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       /*
+         * Find the highest numbered file descriptor for select().
+         * Initialize the set of descriptors to listen to.
+         */
+       FD_ZERO(&fds);
+       for (ii = iflist; ii; ii = ii->ii_next) {
+               FD_SET(ii->ii_fd, &fds);
+               if (ii->ii_fd > maxfd)
+                       maxfd = ii->ii_fd;
+       }
+       while (1) {
+               listeners = fds;
+               if (select(maxfd + 1, &listeners, (struct fd_set *) 0,
+                       (struct fd_set *) 0, (struct timeval *) 0) < 0) {
+                       err(FATAL, "select: %s", strerror(errno));
+                       /* NOTREACHED */
+               }
+               for (ii = iflist; ii; ii = ii->ii_next) {
+                       fd = ii->ii_fd;
+                       if (!FD_ISSET(fd, &listeners))
+                               continue;
+       again:
+                       cc = read(fd, (char *) buf, bufsize);
+                       /* Don't choke when we get ptraced */
+                       if (cc < 0 && errno == EINTR)
+                               goto again;
+                       /* Due to a SunOS bug, after 2^31 bytes, the file
+                        * offset overflows and read fails with EINVAL.  The
+                        * lseek() to 0 will fix things. */
+                       if (cc < 0) {
+                               if (errno == EINVAL &&
+                                   (lseek(fd, 0, SEEK_CUR) + bufsize) < 0) {
+                                       (void) lseek(fd, 0, 0);
+                                       goto again;
+                               }
+                               err(FATAL, "read: %s", strerror(errno));
+                               /* NOTREACHED */
+                       }
+                       /* Loop through the packet(s) */
+#define bhp ((struct bpf_hdr *)bp)
+                       bp = buf;
+                       ep = bp + cc;
+                       while (bp < ep) {
+                               register int caplen, hdrlen;
+
+                               caplen = bhp->bh_caplen;
+                               hdrlen = bhp->bh_hdrlen;
+                               if (rarp_check(bp + hdrlen, caplen))
+                                       rarp_process(ii, bp + hdrlen);
+                               bp += BPF_WORDALIGN(hdrlen + caplen);
+                       }
+               }
+       }
+}
+#ifndef TFTP_DIR
+#define TFTP_DIR "/tftpboot"
+#endif
+
+/*
+ * True if this server can boot the host whose IP address is 'addr'.
+ * This check is made by looking in the tftp directory for the
+ * configuration file.
+ */
+int
+rarp_bootable(addr)
+       u_long  addr;
+{
+       register struct dirent *dent;
+       register DIR *d;
+       char    ipname[9];
+       static DIR *dd = 0;
+
+       (void) sprintf(ipname, "%08X", addr);
+       /* If directory is already open, rewind it.  Otherwise, open it. */
+       if (d = dd)
+               rewinddir(d);
+       else {
+               if (chdir(TFTP_DIR) == -1) {
+                       err(FATAL, "chdir: %s", strerror(errno));
+                       /* NOTREACHED */
+               }
+               d = opendir(".");
+               if (d == 0) {
+                       err(FATAL, "opendir: %s", strerror(errno));
+                       /* NOTREACHED */
+               }
+               dd = d;
+       }
+       while (dent = readdir(d))
+               if (strncmp(dent->d_name, ipname, 8) == 0)
+                       return 1;
+       return 0;
+}
+/*
+ * Given a list of IP addresses, 'alist', return the first address that
+ * is on network 'net'; 'netmask' is a mask indicating the network portion
+ * of the address.
+ */
+u_long
+choose_ipaddr(alist, net, netmask)
+       u_long **alist;
+       u_long  net;
+       u_long  netmask;
+{
+       for (; *alist; ++alist) {
+               if ((**alist & netmask) == net)
+                       return **alist;
+       }
+       return 0;
+}
+/*
+ * Answer the RARP request in 'pkt', on the interface 'ii'.  'pkt' has
+ * already been checked for validity.  The reply is overlaid on the request.
+ */
+void
+rarp_process(ii, pkt)
+       struct if_info *ii;
+       u_char *pkt;
+{
+       struct ether_header *ep;
+       struct hostent *hp;
+       u_long  target_ipaddr;
+       char    ename[256];
+       struct  in_addr in;
+
+       ep = (struct ether_header *) pkt;
+
+       if (ether_ntohost(ename, &ep->ether_shost) != 0 ||
+           (hp = gethostbyname(ename)) == 0)
+               return;
+
+       /* Choose correct address from list. */
+       if (hp->h_addrtype != AF_INET) {
+               err(FATAL, "cannot handle non IP addresses");
+               /* NOTREACHED */
+       }
+       target_ipaddr = choose_ipaddr((u_long **) hp->h_addr_list,
+           ii->ii_ipaddr & ii->ii_netmask, ii->ii_netmask);
+
+       if (target_ipaddr == 0) {
+               in.s_addr = ii->ii_ipaddr & ii->ii_netmask;
+               err(NONFATAL, "cannot find %s on net %s\n",
+                   ename, inet_ntoa(in));
+               return;
+       }
+       if (rarp_bootable(htonl(target_ipaddr)))
+               rarp_reply(ii, ep, target_ipaddr);
+}
+/*
+ * Lookup the ethernet address of the interface attached to the BPF
+ * file descriptor 'fd'; return it in 'eaddr'.
+ */
+void
+lookup_eaddr(ifname, eaddr)
+       char *ifname;
+       u_char *eaddr;
+{
+       char inbuf[8192];
+       struct ifconf ifc;
+       struct ifreq *ifr;
+       struct sockaddr_dl *sdl;
+       int fd;
+       int i, len;
+
+       /* We cannot use SIOCGIFADDR on the BPF descriptor.
+          We must instead get all the interfaces with SIOCGIFCONF
+          and find the right one.  */
+
+       /* Use datagram socket to get Ethernet address. */
+       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               err(FATAL, "socket: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+
+       ifc.ifc_len = sizeof(inbuf);
+       ifc.ifc_buf = inbuf;
+       if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 ||
+           ifc.ifc_len < sizeof(struct ifreq)) {
+               err(FATAL, "lookup_eaddr: SIOGIFCONF: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       ifr = ifc.ifc_req;
+       for (i = 0; i < ifc.ifc_len;
+            i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
+               len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
+               sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
+               if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
+                   sdl->sdl_alen != 6)
+                       continue;
+               if (!strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))) {
+                       bcopy((caddr_t)LLADDR(sdl), (caddr_t)eaddr, 6);
+                       if (dflag)
+                               fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n",
+                                   ifr->ifr_name, eaddr[0], eaddr[1],
+                                   eaddr[2], eaddr[3], eaddr[4], eaddr[5]);
+                       return;
+               }
+       }
+
+       err(FATAL, "lookup_eaddr: Never saw interface `%s'!", ifname);
+}
+/*
+ * Lookup the IP address and network mask of the interface named 'ifname'.
+ */
+void
+lookup_ipaddr(ifname, addrp, netmaskp)
+       char   *ifname;
+       u_long *addrp;
+       u_long *netmaskp;
+{
+       int     fd;
+       struct ifreq ifr;
+
+       /* Use datagram socket to get IP address. */
+       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               err(FATAL, "socket: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       (void) strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
+       if (ioctl(fd, SIOCGIFADDR, (char *) &ifr) < 0) {
+               err(FATAL, "SIOCGIFADDR: %s", strerror(errno));
+               /* NOTREACHED */
+       }
+       *addrp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
+       if (ioctl(fd, SIOCGIFNETMASK, (char *) &ifr) < 0) {
+               perror("SIOCGIFNETMASK");
+               exit(1);
+       }
+       *netmaskp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr;
+       /* If SIOCGIFNETMASK didn't work, figure out a mask from the IP
+        * address class. */
+       if (*netmaskp == 0)
+               *netmaskp = ipaddrtonetmask(*addrp);
+
+       (void) close(fd);
+}
+/*
+ * Poke the kernel arp tables with the ethernet/ip address combinataion
+ * given.  When processing a reply, we must do this so that the booting
+ * host (i.e. the guy running rarpd), won't try to ARP for the hardware
+ * address of the guy being booted (he cannot answer the ARP).
+ */
+void
+update_arptab(ep, ipaddr)
+       u_char *ep;
+       u_long  ipaddr;
+{
+       int     s;
+       struct arpreq request;
+       struct sockaddr_in *sin;
+
+       request.arp_flags = 0;
+       sin = (struct sockaddr_in *) & request.arp_pa;
+       sin->sin_family = AF_INET;
+       sin->sin_addr.s_addr = ipaddr;
+       request.arp_ha.sa_family = AF_UNSPEC;
+       /* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN,
+          because AF_UNSPEC is zero and the kernel assumes that a zero
+          sa_family means that the real sa_family value is in sa_len.  */
+       request.arp_ha.sa_len = 16; /* XXX */
+       bcopy((char *) ep, (char *) request.arp_ha.sa_data, 6);
+
+#if 0
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (ioctl(s, SIOCSARP, (caddr_t) & request) < 0) {
+               err(NONFATAL, "SIOCSARP: %s", strerror(errno));
+       }
+       (void) close(s);
+#endif
+}
+/*
+ * Build a reverse ARP packet and sent it out on the interface.
+ * 'ep' points to a valid ARPOP_REVREQUEST.  The ARPOP_REVREPLY is built
+ * on top of the request, then written to the network.
+ *
+ * RFC 903 defines the ether_arp fields as follows.  The following comments
+ * are taken (more or less) straight from this document.
+ *
+ * ARPOP_REVREQUEST
+ *
+ * arp_sha is the hardware address of the sender of the packet.
+ * arp_spa is undefined.
+ * arp_tha is the 'target' hardware address.
+ *   In the case where the sender wishes to determine his own
+ *   protocol address, this, like arp_sha, will be the hardware
+ *   address of the sender.
+ * arp_tpa is undefined.
+ *
+ * ARPOP_REVREPLY
+ *
+ * arp_sha is the hardware address of the responder (the sender of the
+ *   reply packet).
+ * arp_spa is the protocol address of the responder (see the note below).
+ * arp_tha is the hardware address of the target, and should be the same as
+ *   that which was given in the request.
+ * arp_tpa is the protocol address of the target, that is, the desired address.
+ *
+ * Note that the requirement that arp_spa be filled in with the responder's
+ * protocol is purely for convenience.  For instance, if a system were to use
+ * both ARP and RARP, then the inclusion of the valid protocol-hardware
+ * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
+ * ARP request.
+ */
+void
+rarp_reply(ii, ep, ipaddr)
+       struct if_info *ii;
+       struct ether_header *ep;
+       u_long  ipaddr;
+{
+       int     n;
+       struct ether_arp *ap = (struct ether_arp *) (ep + 1);
+       int     len;
+
+       update_arptab((u_char *) & ap->arp_sha, ipaddr);
+
+       /* Build the rarp reply by modifying the rarp request in place. */
+       ep->ether_type = htons(ETHERTYPE_REVARP);
+       ap->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
+       ap->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
+       ap->arp_op = htons(ARPOP_REVREPLY);
+
+       bcopy((char *) &ap->arp_sha, (char *) &ep->ether_dhost, 6);
+       bcopy((char *) ii->ii_eaddr, (char *) &ep->ether_shost, 6);
+       bcopy((char *) ii->ii_eaddr, (char *) &ap->arp_sha, 6);
+
+       bcopy((char *) &ipaddr, (char *) ap->arp_tpa, 4);
+       /* Target hardware is unchanged. */
+       bcopy((char *) &ii->ii_ipaddr, (char *) ap->arp_spa, 4);
+
+       len = sizeof(*ep) + sizeof(*ap);
+       n = write(ii->ii_fd, (char *) ep, len);
+       if (n != len) {
+               err(NONFATAL, "write: only %d of %d bytes written", n, len);
+       }
+}
+/*
+ * Get the netmask of an IP address.  This routine is used if
+ * SIOCGIFNETMASK doesn't work.
+ */
+u_long
+ipaddrtonetmask(addr)
+       u_long  addr;
+{
+       if (IN_CLASSA(addr))
+               return IN_CLASSA_NET;
+       if (IN_CLASSB(addr))
+               return IN_CLASSB_NET;
+       if (IN_CLASSC(addr))
+               return IN_CLASSC_NET;
+       err(FATAL, "unknown IP address class: %08X", addr);
+       /* NOTREACHED */
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(int fatal, const char *fmt,...)
+#else
+err(fmt, va_alist)
+       int     fatal;
+       char   *fmt;
+va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       if (dflag) {
+               if (fatal)
+                       (void) fprintf(stderr, "rarpd: error: ");
+               else
+                       (void) fprintf(stderr, "rarpd: warning: ");
+               (void) vfprintf(stderr, fmt, ap);
+               (void) fprintf(stderr, "\n");
+       }
+       vsyslog(LOG_ERR, fmt, ap);
+       va_end(ap);
+       if (fatal)
+               exit(1);
+       /* NOTREACHED */
+}
+
+void
+#if __STDC__
+debug(const char *fmt,...)
+#else
+debug(fmt, va_alist)
+       char   *fmt;
+va_dcl
+#endif
+{
+       va_list ap;
+
+       if (dflag) {
+#if __STDC__
+               va_start(ap, fmt);
+#else
+               va_start(ap);
+#endif
+               (void) fprintf(stderr, "rarpd: ");
+               (void) vfprintf(stderr, fmt, ap);
+               va_end(ap);
+               (void) fprintf(stderr, "\n");
+       }
+}
diff --git a/rbootd.tproj/Makefile b/rbootd.tproj/Makefile
new file mode 100644 (file)
index 0000000..6a4e127
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rbootd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = defs.h pathnames.h rmp.h rmp_var.h
+
+CFILES = bpf.c conf.c parseconf.c rbootd.c rmpproto.c utils.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rbootd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rbootd.tproj/Makefile.postamble b/rbootd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7ede358
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
diff --git a/rbootd.tproj/Makefile.preamble b/rbootd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dcbd1c8
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
diff --git a/rbootd.tproj/PB.project b/rbootd.tproj/PB.project
new file mode 100644 (file)
index 0000000..4423a10
--- /dev/null
@@ -0,0 +1,39 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (defs.h, pathnames.h, rmp.h, rmp_var.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (bpf.c, conf.c, parseconf.c, rbootd.c, rmpproto.c, utils.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rbootd.8); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rbootd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rbootd.tproj/bpf.c b/rbootd.tproj/bpf.c
new file mode 100644 (file)
index 0000000..ed21480
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)bpf.c       8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: bpf.c 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)bpf.c      8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/bpf.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "defs.h"
+#include "pathnames.h"
+
+static int BpfFd = -1;
+static unsigned BpfLen = 0;
+static u_char *BpfPkt = NULL;
+
+/*
+**  BpfOpen -- Open and initialize a BPF device.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             File descriptor of opened BPF device (for select() etc).
+**
+**     Side Effects:
+**             If an error is encountered, the program terminates here.
+*/
+int
+BpfOpen()
+{
+       struct ifreq ifr;
+       char bpfdev[32];
+       int n = 0;
+
+       /*
+        *  Open the first available BPF device.
+        */
+       do {
+               (void) sprintf(bpfdev, _PATH_BPF, n++);
+               BpfFd = open(bpfdev, O_RDWR);
+       } while (BpfFd < 0 && (errno == EBUSY || errno == EPERM));
+
+       if (BpfFd < 0) {
+               syslog(LOG_ERR, "bpf: no available devices: %m");
+               Exit(0);
+       }
+
+       /*
+        *  Set interface name for bpf device, get data link layer
+        *  type and make sure it's type Ethernet.
+        */
+       (void) strncpy(ifr.ifr_name, IntfName, sizeof(ifr.ifr_name));
+       if (ioctl(BpfFd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+               syslog(LOG_ERR, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName);
+               Exit(0);
+       }
+
+       /*
+        *  Make sure we are dealing with an Ethernet device.
+        */
+       if (ioctl(BpfFd, BIOCGDLT, (caddr_t)&n) < 0) {
+               syslog(LOG_ERR, "bpf: ioctl(BIOCGDLT): %m");
+               Exit(0);
+       }
+       if (n != DLT_EN10MB) {
+               syslog(LOG_ERR,"bpf: %s: data-link type %d unsupported",
+                      IntfName, n);
+               Exit(0);
+       }
+
+       /*
+        *  On read(), return packets immediately (do not buffer them).
+        */
+       n = 1;
+       if (ioctl(BpfFd, BIOCIMMEDIATE, (caddr_t)&n) < 0) {
+               syslog(LOG_ERR, "bpf: ioctl(BIOCIMMEDIATE): %m");
+               Exit(0);
+       }
+
+       /*
+        *  Try to enable the chip/driver's multicast address filter to
+        *  grab our RMP address.  If this fails, try promiscuous mode.
+        *  If this fails, there's no way we are going to get any RMP
+        *  packets so just exit here.
+        */
+#ifdef MSG_EOR
+       ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2;
+#endif
+       ifr.ifr_addr.sa_family = AF_UNSPEC;
+       bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN);
+       if (ioctl(BpfFd, SIOCADDMULTI, (caddr_t)&ifr) < 0) {
+               syslog(LOG_WARNING,
+                   "bpf: can't add mcast addr (%m), setting promiscuous mode");
+
+               if (ioctl(BpfFd, BIOCPROMISC, (caddr_t)0) < 0) {
+                       syslog(LOG_ERR, "bpf: can't set promiscuous mode: %m");
+                       Exit(0);
+               }
+       }
+
+       /*
+        *  Ask BPF how much buffer space it requires and allocate one.
+        */
+       if (ioctl(BpfFd, BIOCGBLEN, (caddr_t)&BpfLen) < 0) {
+               syslog(LOG_ERR, "bpf: ioctl(BIOCGBLEN): %m");
+               Exit(0);
+       }
+       if (BpfPkt == NULL)
+               BpfPkt = (u_char *)malloc(BpfLen);
+
+       if (BpfPkt == NULL) {
+               syslog(LOG_ERR, "bpf: out of memory (%u bytes for bpfpkt)",
+                      BpfLen);
+               Exit(0);
+       }
+
+       /*
+        *  Write a little program to snarf RMP Boot packets and stuff
+        *  it down BPF's throat (i.e. set up the packet filter).
+        */
+       {
+#define        RMP     ((struct rmp_packet *)0)
+               static struct bpf_insn bpf_insn[] = {
+                   { BPF_LD|BPF_B|BPF_ABS,  0, 0, (long)&RMP->hp_llc.dsap },
+                   { BPF_JMP|BPF_JEQ|BPF_K, 0, 5, IEEE_DSAP_HP },
+                   { BPF_LD|BPF_H|BPF_ABS,  0, 0, (long)&RMP->hp_llc.cntrl },
+                   { BPF_JMP|BPF_JEQ|BPF_K, 0, 3, IEEE_CNTL_HP },
+                   { BPF_LD|BPF_H|BPF_ABS,  0, 0, (long)&RMP->hp_llc.dxsap },
+                   { BPF_JMP|BPF_JEQ|BPF_K, 0, 1, HPEXT_DXSAP },
+                   { BPF_RET|BPF_K,         0, 0, RMP_MAX_PACKET },
+                   { BPF_RET|BPF_K,         0, 0, 0x0 }
+               };
+#undef RMP
+               static struct bpf_program bpf_pgm = {
+                   sizeof(bpf_insn)/sizeof(bpf_insn[0]), bpf_insn
+               };
+
+               if (ioctl(BpfFd, BIOCSETF, (caddr_t)&bpf_pgm) < 0) {
+                       syslog(LOG_ERR, "bpf: ioctl(BIOCSETF): %m");
+                       Exit(0);
+               }
+       }
+
+       return(BpfFd);
+}
+
+/*
+**  BPF GetIntfName -- Return the name of a network interface attached to
+**             the system, or 0 if none can be found.  The interface
+**             must be configured up; the lowest unit number is
+**             preferred; loopback is ignored.
+**
+**     Parameters:
+**             errmsg - if no network interface found, *errmsg explains why.
+**
+**     Returns:
+**             A (static) pointer to interface name, or NULL on error.
+**
+**     Side Effects:
+**             None.
+*/
+char *
+BpfGetIntfName(errmsg)
+       char **errmsg;
+{
+       struct ifreq ibuf[8], *ifrp, *ifend, *mp;
+       struct ifconf ifc;
+       int fd;
+       int minunit, n;
+       char *cp;
+       static char device[sizeof(ifrp->ifr_name)];
+       static char errbuf[128] = "No Error!";
+
+       if (errmsg != NULL)
+               *errmsg = errbuf;
+
+       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               (void) strcpy(errbuf, "bpf: socket: %m");
+               return(NULL);
+       }
+       ifc.ifc_len = sizeof ibuf;
+       ifc.ifc_buf = (caddr_t)ibuf;
+
+#ifdef OSIOCGIFCONF
+       if (ioctl(fd, OSIOCGIFCONF, (char *)&ifc) < 0 ||
+           ifc.ifc_len < sizeof(struct ifreq)) {
+               (void) strcpy(errbuf, "bpf: ioctl(OSIOCGIFCONF): %m");
+               return(NULL);
+       }
+#else
+       if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
+           ifc.ifc_len < sizeof(struct ifreq)) {
+               (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFCONF): %m");
+               return(NULL);
+       }
+#endif
+       ifrp = ibuf;
+       ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
+       
+       mp = 0;
+       minunit = 666;
+       for (; ifrp < ifend; ++ifrp) {
+               if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) {
+                       (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFFLAGS): %m");
+                       return(NULL);
+               }
+
+               /*
+                *  If interface is down or this is the loopback interface,
+                *  ignore it.
+                */
+               if ((ifrp->ifr_flags & IFF_UP) == 0 ||
+#ifdef IFF_LOOPBACK
+                   (ifrp->ifr_flags & IFF_LOOPBACK))
+#else
+                   (strcmp(ifrp->ifr_name, "lo0") == 0))
+#endif
+                       continue;
+
+               for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
+                       ;
+               n = atoi(cp);
+               if (n < minunit) {
+                       minunit = n;
+                       mp = ifrp;
+               }
+       }
+
+       (void) close(fd);
+       if (mp == 0) {
+               (void) strcpy(errbuf, "bpf: no interfaces found");
+               return(NULL);
+       }
+
+       (void) strcpy(device, mp->ifr_name);
+       return(device);
+}
+
+/*
+**  BpfRead -- Read packets from a BPF device and fill in `rconn'.
+**
+**     Parameters:
+**             rconn - filled in with next packet.
+**             doread - is True if we can issue a read() syscall.
+**
+**     Returns:
+**             True if `rconn' contains a new packet, False otherwise.
+**
+**     Side Effects:
+**             None.
+*/
+int
+BpfRead(rconn, doread)
+       RMPCONN *rconn;
+       int doread;
+{
+       register int datlen, caplen, hdrlen;
+       static u_char *bp = NULL, *ep = NULL;
+       int cc;
+
+       /*
+        *  The read() may block, or it may return one or more packets.
+        *  We let the caller decide whether or not we can issue a read().
+        */
+       if (doread) {
+               if ((cc = read(BpfFd, (char *)BpfPkt, (int)BpfLen)) < 0) {
+                       syslog(LOG_ERR, "bpf: read: %m");
+                       return(0);
+               } else {
+                       bp = BpfPkt;
+                       ep = BpfPkt + cc;
+               }
+       }
+
+#define bhp ((struct bpf_hdr *)bp)
+       /*
+        *  If there is a new packet in the buffer, stuff it into `rconn'
+        *  and return a success indication.
+        */
+       if (bp < ep) {
+               datlen = bhp->bh_datalen;
+               caplen = bhp->bh_caplen;
+               hdrlen = bhp->bh_hdrlen;
+
+               if (caplen != datlen)
+                       syslog(LOG_ERR,
+                              "bpf: short packet dropped (%d of %d bytes)",
+                              caplen, datlen);
+               else if (caplen > sizeof(struct rmp_packet))
+                       syslog(LOG_ERR, "bpf: large packet dropped (%d bytes)",
+                              caplen);
+               else {
+                       rconn->rmplen = caplen;
+                       bcopy((char *)&bhp->bh_tstamp, (char *)&rconn->tstamp,
+                             sizeof(struct timeval));
+                       bcopy((char *)bp + hdrlen, (char *)&rconn->rmp, caplen);
+               }
+               bp += BPF_WORDALIGN(caplen + hdrlen);
+               return(1);
+       }
+#undef bhp
+
+       return(0);
+}
+
+/*
+**  BpfWrite -- Write packet to BPF device.
+**
+**     Parameters:
+**             rconn - packet to send.
+**
+**     Returns:
+**             True if write succeeded, False otherwise.
+**
+**     Side Effects:
+**             None.
+*/
+int
+BpfWrite(rconn)
+       RMPCONN *rconn;
+{
+       if (write(BpfFd, (char *)&rconn->rmp, rconn->rmplen) < 0) {
+               syslog(LOG_ERR, "write: %s: %m", EnetStr(rconn));
+               return(0);
+       }
+
+       return(1);
+}
+
+/*
+**  BpfClose -- Close a BPF device.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             None.
+*/
+void
+BpfClose()
+{
+       struct ifreq ifr;
+
+       if (BpfPkt != NULL) {
+               free((char *)BpfPkt);
+               BpfPkt = NULL;
+       }
+
+       if (BpfFd == -1)
+               return;
+
+#ifdef MSG_EOR
+       ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2;
+#endif
+       ifr.ifr_addr.sa_family = AF_UNSPEC;
+       bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN);
+       if (ioctl(BpfFd, SIOCDELMULTI, (caddr_t)&ifr) < 0)
+               (void) ioctl(BpfFd, BIOCPROMISC, (caddr_t)0);
+
+       (void) close(BpfFd);
+       BpfFd = -1;
+}
diff --git a/rbootd.tproj/conf.c b/rbootd.tproj/conf.c
new file mode 100644 (file)
index 0000000..e61a0f3
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)conf.c      8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: conf.c 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)conf.c     8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include "defs.h"
+#include "pathnames.h"
+
+/*
+**  Define (and possibly initialize) global variables here.
+**
+**  Caveat:
+**     The maximum number of bootable files (`char *BootFiles[]') is
+**     limited to C_MAXFILE (i.e. the maximum number of files that
+**     can be spec'd in the configuration file).  This was done to
+**     simplify the boot file search code.
+*/
+
+char   *ProgName;                              /* path-stripped argv[0] */
+char   MyHost[MAXHOSTNAMELEN+1];               /* host name */
+int    MyPid;                                  /* process id */
+int    DebugFlg = 0;                           /* set true if debugging */
+int    BootAny = 0;                            /* set true if we boot anyone */
+
+char   *ConfigFile = NULL;                     /* configuration file */
+char   *DfltConfig = _PATH_RBOOTDCONF;         /* default configuration file */
+char   *PidFile = _PATH_RBOOTDPID;             /* file w/pid of server */
+char   *BootDir = _PATH_RBOOTDLIB;             /* directory w/boot files */
+char   *DbgFile = _PATH_RBOOTDDBG;             /* debug output file */
+
+FILE   *DbgFp = NULL;                          /* debug file pointer */
+char   *IntfName = NULL;                       /* intf we are attached to */
+
+u_short        SessionID = 0;                          /* generated session ID */
+
+char   *BootFiles[C_MAXFILE];                  /* list of boot files */
+
+CLIENT *Clients = NULL;                        /* list of addrs we'll accept */
+RMPCONN        *RmpConns = NULL;                       /* list of active connections */
+
+char   RmpMcastAddr[RMP_ADDRLEN] = RMP_ADDR;   /* RMP multicast address */
diff --git a/rbootd.tproj/defs.h b/rbootd.tproj/defs.h
new file mode 100644 (file)
index 0000000..976ffc1
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: defs.h 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#include "rmp.h"
+#include "rmp_var.h"
+
+/*
+**  Common #define's and external variables.  All other files should
+**  include this.
+*/
+
+/*
+ *  This may be defined in <sys/param.h>, if not, it's defined here.
+ */
+#ifndef        MAXHOSTNAMELEN
+#define        MAXHOSTNAMELEN 64
+#endif
+
+/*
+ *  SIGUSR1 and SIGUSR2 are defined in <signal.h> for 4.3BSD systems.
+ */
+#ifndef SIGUSR1
+#define        SIGUSR1 SIGEMT
+#endif
+#ifndef SIGUSR2
+#define        SIGUSR2 SIGFPE
+#endif
+
+/*
+ *  These can be faster & more efficient than strcmp()/strncmp()...
+ */
+#define        STREQN(s1,s2)           ((*s1 == *s2) && (strcmp(s1,s2) == 0))
+#define        STRNEQN(s1,s2,n)        ((*s1 == *s2) && (strncmp(s1,s2,n) == 0))
+
+/*
+ *  Configuration file limitations.
+ */
+#define        C_MAXFILE       10              /* max number of boot-able files */
+#define        C_LINELEN       1024            /* max length of line */
+
+/*
+ *  Direction of packet (used as argument to DispPkt).
+ */
+#define        DIR_RCVD        0
+#define        DIR_SENT        1
+#define        DIR_NONE        2
+
+/*
+ *  These need not be functions, so...
+ */
+#define        FreeStr(str)    free(str)
+#define        FreeClient(cli) free(cli)
+#define        GenSessID()     (++SessionID ? SessionID: ++SessionID)
+
+/*
+ *  Converting an Ethernet address to a string is done in many routines.
+ *  Using `rmp.hp_hdr.saddr' works because this field is *never* changed;
+ *  it will *always* contain the source address of the packet.
+ */
+#define        EnetStr(rptr)   GetEtherAddr(&(rptr)->rmp.hp_hdr.saddr[0])
+
+/*
+ *  Every machine we can boot will have one of these allocated for it
+ *  (unless there are no restrictions on who we can boot).
+ */
+typedef struct client_s {
+       u_char                  addr[RMP_ADDRLEN];      /* addr of machine */
+       char                    *files[C_MAXFILE];      /* boot-able files */
+       struct client_s         *next;                  /* ptr to next */
+} CLIENT;
+
+/*
+ *  Every active connection has one of these allocated for it.
+ */
+typedef struct rmpconn_s {
+       struct rmp_packet       rmp;                    /* RMP packet */
+       int                     rmplen;                 /* length of packet */
+       struct timeval          tstamp;                 /* last time active */
+       int                     bootfd;                 /* open boot file */
+       struct rmpconn_s        *next;                  /* ptr to next */
+} RMPCONN;
+
+/*
+ *  All these variables are defined in "conf.c".
+ */
+extern char    *ProgName;              /* path-stripped argv[0] */
+extern char    MyHost[];               /* this hosts' name */
+extern int     MyPid;                  /* this processes' ID */
+extern int     DebugFlg;               /* set true if debugging */
+extern int     BootAny;                /* set true if we can boot anyone */
+
+extern char    *ConfigFile;            /* configuration file */
+extern char    *DfltConfig;            /* default configuration file */
+extern char    *DbgFile;               /* debug output file */
+extern char    *PidFile;               /* file containing pid of server */
+extern char    *BootDir;               /* directory w/boot files */
+
+extern FILE    *DbgFp;                 /* debug file pointer */
+extern char    *IntfName;              /* interface we are attached to */
+
+extern u_short SessionID;              /* generated session ID */
+
+extern char    *BootFiles[];           /* list of boot files */
+
+extern CLIENT  *Clients;               /* list of addrs we'll accept */
+extern RMPCONN *RmpConns;              /* list of active connections */
+
+extern char    RmpMcastAddr[];         /* RMP multicast address */
+
+void    AddConn __P((RMPCONN *));
+int     BootDone __P((RMPCONN *));
+void    BpfClose __P((void));
+char   *BpfGetIntfName __P((char **));
+int     BpfOpen __P((void));
+int     BpfRead __P((RMPCONN *, int));
+int     BpfWrite __P((RMPCONN *));
+void    DebugOff __P((int));
+void    DebugOn __P((int));
+void    DispPkt __P((RMPCONN *, int));
+void    DoTimeout __P((void));
+void    DspFlnm __P((u_int, char *));
+void    Exit __P((int));
+CLIENT *FindClient __P((RMPCONN *));
+RMPCONN        *FindConn __P((RMPCONN *));
+void    FreeClients __P((void));
+void    FreeConn __P((RMPCONN *));
+void    FreeConns __P((void));
+int     GetBootFiles __P((void));
+char   *GetEtherAddr __P((u_char *));
+CLIENT *NewClient __P((u_char *));
+RMPCONN        *NewConn __P((RMPCONN *));
+char   *NewStr __P((char *));
+u_char *ParseAddr __P((char *));
+int     ParseConfig __P((void));
+void    ProcessPacket __P((RMPCONN *, CLIENT *));
+void    ReConfig __P((int));
+void    RemoveConn __P((RMPCONN *));
+int     SendBootRepl __P((struct rmp_packet *, RMPCONN *, char *[]));
+int     SendFileNo __P((struct rmp_packet *, RMPCONN *, char *[]));
+int     SendPacket __P((RMPCONN *));
+int     SendReadRepl __P((RMPCONN *));
+int     SendServerID __P((RMPCONN *));
diff --git a/rbootd.tproj/parseconf.c b/rbootd.tproj/parseconf.c
new file mode 100644 (file)
index 0000000..ddf2f19
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)parseconf.c 8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: parseconf.c 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)parseconf.c        8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include "defs.h"
+
+/*
+**  ParseConfig -- parse the config file into linked list of clients.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             1 on success, 0 otherwise.
+**
+**     Side Effects:
+**             - Linked list of clients will be (re)allocated.
+**
+**     Warnings:
+**             - GetBootFiles() must be called before this routine
+**               to create a linked list of default boot files.
+*/
+int
+ParseConfig()
+{
+       FILE *fp;
+       CLIENT *client;
+       u_char *addr;
+       char line[C_LINELEN];
+       register char *cp, *bcp;
+       register int i, j;
+       int omask, linecnt = 0;
+
+       if (BootAny)                            /* ignore config file */
+               return(1);
+
+       FreeClients();                          /* delete old list of clients */
+
+       if ((fp = fopen(ConfigFile, "r")) == NULL) {
+               syslog(LOG_ERR, "ParseConfig: can't open config file (%s)",
+                      ConfigFile);
+               return(0);
+       }
+
+       /*
+        *  We've got to block SIGHUP to prevent reconfiguration while
+        *  dealing with the linked list of Clients.  This can be done
+        *  when actually linking the new client into the list, but
+        *  this could have unexpected results if the server was HUP'd
+        *  whilst reconfiguring.  Hence, it is done here.
+        */
+       omask = sigblock(sigmask(SIGHUP));
+
+       /*
+        *  GETSTR positions `bcp' at the start of the current token,
+        *  and null terminates it.  `cp' is positioned at the start
+        *  of the next token.  spaces & commas are separators.
+        */
+#define GETSTR while (isspace(*cp) || *cp == ',') cp++;        \
+               bcp = cp;                                       \
+               while (*cp && *cp!=',' && !isspace(*cp)) cp++;  \
+               if (*cp) *cp++ = '\0'
+
+       /*
+        *  For each line, parse it into a new CLIENT struct.
+        */
+       while (fgets(line, C_LINELEN, fp) != NULL) {
+               linecnt++;                              /* line counter */
+
+               if (*line == '\0' || *line == '#')      /* ignore comment */
+                       continue;
+
+               if ((cp = index(line,'#')) != NULL)     /* trash comments */
+                       *cp = '\0';
+
+               cp = line;                              /* init `cp' */
+               GETSTR;                                 /* get RMP addr */
+               if (bcp == cp)                          /* all delimiters */
+                       continue;
+
+               /*
+                *  Get an RMP address from a string.  Abort on failure.
+                */
+               if ((addr = ParseAddr(bcp)) == NULL) {
+                       syslog(LOG_ERR,
+                              "ParseConfig: line %d: cant parse <%s>",
+                              linecnt, bcp);
+                       continue;
+               }
+
+               if ((client = NewClient(addr)) == NULL) /* alloc new client */
+                       continue;
+
+               GETSTR;                                 /* get first file */
+
+               /*
+                *  If no boot files are spec'd, use the default list.
+                *  Otherwise, validate each file (`bcp') against the
+                *  list of boot-able files.
+                */
+               i = 0;
+               if (bcp == cp)                          /* no files spec'd */
+                       for (; i < C_MAXFILE && BootFiles[i] != NULL; i++)
+                               client->files[i] = BootFiles[i];
+               else {
+                       do {
+                               /*
+                                *  For each boot file spec'd, make sure it's
+                                *  in our list.  If so, include a pointer to
+                                *  it in the CLIENT's list of boot files.
+                                */
+                               for (j = 0; ; j++) {
+                                       if (j==C_MAXFILE||BootFiles[j]==NULL) {
+                                               syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)",
+                                                      linecnt, bcp);
+                                               break;
+                                       }
+                                       if (STREQN(BootFiles[j], bcp)) {
+                                               if (i < C_MAXFILE)
+                                                       client->files[i++] =
+                                                           BootFiles[j];
+                                               else
+                                                       syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)",
+                                                              linecnt, bcp);
+                                               break;
+                                       }
+                               }
+                               GETSTR;                 /* get next file */
+                       } while (bcp != cp);
+
+                       /*
+                        *  Restricted list of boot files were spec'd,
+                        *  however, none of them were found.  Since we
+                        *  apparently cant let them boot "just anything",
+                        *  the entire record is invalidated.
+                        */
+                       if (i == 0) {
+                               FreeClient(client);     
+                               continue;
+                       }
+               }
+
+               /*
+                *  Link this client into the linked list of clients.
+                *  SIGHUP has already been blocked.
+                */
+               if (Clients)
+                       client->next = Clients;
+               Clients = client;
+       }
+
+       (void) fclose(fp);                              /* close config file */
+
+       (void) sigsetmask(omask);                       /* reset signal mask */
+
+       return(1);                                      /* return success */
+}
+
+/*
+**  ParseAddr -- Parse a string containing an RMP address.
+**
+**     This routine is fairly liberal at parsing an RMP address.  The
+**     address must contain 6 octets consisting of between 0 and 2 hex
+**     chars (upper/lower case) separated by colons.  If two colons are
+**     together (e.g. "::", the octet between them is recorded as being
+**     zero.  Hence, the following addrs are all valid and parse to the
+**     same thing:
+**
+**             08:00:09:00:66:ad       8::9:0:66:AD    8::9::66:aD
+**
+**     For clarity, an RMP address is really an Ethernet address, but
+**     since the HP boot code uses IEEE 802.3, it's really an IEEE
+**     802.3 address.  Of course, all of these are identical.
+**
+**     Parameters:
+**             str - string representation of an RMP address.
+**
+**     Returns:
+**             pointer to a static array of RMP_ADDRLEN bytes.
+**
+**     Side Effects:
+**             None.
+**
+**     Warnings:
+**             - The return value points to a static buffer; it must
+**               be copied if it's to be saved.
+**             - For speed, we assume a u_char consists of 8 bits.
+*/
+u_char *
+ParseAddr(str)
+       char *str;
+{
+       static u_char addr[RMP_ADDRLEN];
+       register char *cp;
+       register unsigned i;
+       register int part, subpart;
+
+       bzero((char *)&addr[0], RMP_ADDRLEN);   /* zero static buffer */
+
+       part = subpart = 0;
+       for (cp = str; *cp; cp++) {
+               /*
+                *  A colon (`:') must be used to delimit each octet.
+                */
+               if (*cp == ':') {
+                       if (++part == RMP_ADDRLEN)      /* too many parts */
+                               return(NULL);
+                       subpart = 0;
+                       continue;
+               }
+
+               /*
+                *  Convert hex character to an integer.
+                */
+               if (isdigit(*cp))
+                       i = *cp - '0';
+               else {
+                       i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10;
+                       if (i < 10 || i > 15)           /* not a hex char */
+                               return(NULL);
+               }
+
+               if (subpart++) {
+                       if (subpart > 2)                /* too many hex chars */
+                               return(NULL);
+                       addr[part] <<= 4;
+               }
+               addr[part] |= i;
+       }
+
+       if (part != (RMP_ADDRLEN-1))                    /* too few parts */
+               return(NULL);
+
+       return(&addr[0]);
+}
+
+/*
+**  GetBootFiles -- record list of files in current (boot) directory.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Number of boot files on success, 0 on failure.
+**
+**     Side Effects:
+**             Strings in `BootFiles' are freed/allocated.
+**
+**     Warnings:
+**             - After this routine is called, ParseConfig() must be
+**               called to re-order it's list of boot file pointers.
+*/
+int
+GetBootFiles()
+{
+       DIR *dfd;
+       struct stat statb;
+       register struct dirent *dp;
+       register int i;
+
+       /*
+        *  Free the current list of boot files.
+        */
+       for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) {
+               FreeStr(BootFiles[i]);
+               BootFiles[i] = NULL;
+       }
+
+       /*
+        *  Open current directory to read boot file names.
+        */
+       if ((dfd = opendir(".")) == NULL) {     /* open BootDir */
+               syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n",
+                      BootDir);
+               return(0);
+       }
+
+       /*
+        *  Read each boot file name and allocate space for it in the
+        *  list of boot files (BootFiles).  All boot files read after
+        *  C_MAXFILE will be ignored.
+        */
+       i = 0;
+       for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) {
+               if (stat(dp->d_name, &statb) < 0 ||
+                   (statb.st_mode & S_IFMT) != S_IFREG)
+                       continue;
+               if (i == C_MAXFILE)
+                       syslog(LOG_ERR,
+                              "GetBootFiles: too many boot files (%s ignored)",
+                              dp->d_name);
+               else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL)
+                       i++;
+       }
+
+       (void) closedir(dfd);                   /* close BootDir */
+
+       if (i == 0)                             /* cant find any boot files */
+               syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir);
+
+       return(i);
+}
diff --git a/rbootd.tproj/pathnames.h b/rbootd.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..15765da
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: pathnames.h 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#define        _PATH_BPF               "/dev/bpf%d"
+#define        _PATH_RBOOTDCONF        "/etc/rbootd.conf"
+#define        _PATH_RBOOTDDBG         "/tmp/rbootd.dbg"
+#define        _PATH_RBOOTDLIB         "/usr/mdec/rbootd"
+#define        _PATH_RBOOTDPID         "/var/run/rbootd.pid"
diff --git a/rbootd.tproj/rbootd.8 b/rbootd.tproj/rbootd.8
new file mode 100644 (file)
index 0000000..f4eb364
--- /dev/null
@@ -0,0 +1,156 @@
+.\" Copyright (c) 1988, 1992 The University of Utah and the Center
+.\"    for Software Science (CSS).
+.\" Copyright (c) 1992, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Center for Software Science of the University of Utah Computer
+.\" Science Department.  CSS requests users of this software to return
+.\" to css-dist@cs.utah.edu any improvements that they make and grant
+.\" CSS redistribution rights.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)rbootd.8    8.2 (Berkeley) 12/11/93
+.\"
+.\" Utah $Hdr: rbootd.man 3.1 92/07/06$
+.\" Author: Jeff Forys, University of Utah CSS
+.\"
+.Dd "December 11, 1993"
+.Dt RBOOTD 8
+.Os
+.Sh NAME
+.Nm rbootd
+.Nd HP remote boot server
+.Sh SYNOPSIS
+.Nm rbootd
+.Op Fl ad
+.Op Fl i Ar interface
+.Op config_file
+.Sh DESCRIPTION
+The
+.Nm rbootd
+utility services boot requests from Hewlett-Packard workstations over a
+local area network.
+All boot files must reside in the boot file directory; further, if a
+client supplies path information in its boot request, it will be silently
+stripped away before processing.
+By default,
+.Nm rbootd
+only responds to requests from machines listed in its configuration file.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl a
+Respond to boot requests from any machine.
+The configuration file is ignored if this option is specified.
+.It Fl d
+Run
+.Nm rbootd
+in debug mode.
+Packets sent and received are displayed to the terminal.
+.It Fl i Ar interface
+Service boot requests on specified interface.
+If unspecified,
+.Nm rbootd
+searches the system interface list for the lowest numbered, configured
+``up'' interface (excluding loopback).
+Ties are broken by choosing the earliest match.
+.El
+.Pp
+Specifying
+.Ar config_file
+on the command line causes
+.Nm rbootd
+to use a different configuration file from the default.
+.Pp
+The configuration file is a text file where each line describes a particular
+machine.
+A line must start with a machine's Ethernet address followed by an optional
+list of boot file names.
+An Ethernet address is specified in hexadecimal with each of its six octets
+separated by a colon.
+The boot file names come from the boot file directory.
+The ethernet address and boot file(s) must be separated by white-space
+and/or comma characters.
+A pound sign causes the remainder of a line to be ignored.
+.Pp
+Here is a sample configuration file:
+.Bl -column 08:00:09:0:66:ad SYSHPBSD,SYSHPUX "# vandy (anything)"
+.It #
+.It # ethernet addr    boot file(s)    comments
+.It #
+.It 08:00:09:0:66:ad   SYSHPBSD        # snake (4.3BSD)
+.It 08:00:09:0:59:5b           # vandy (anything)
+.It 8::9:1:C6:75       SYSHPBSD,SYSHPUX        # jaguar (either)
+.El
+.Pp
+.Nm Rbootd
+logs status and error messages via
+.Xr syslog 3 .
+A startup message is always logged, and in the case of fatal errors (or
+deadly signals) a message is logged announcing the server's termination.
+In general, a non-fatal error is handled by ignoring the event that caused
+it (e.g. an invalid Ethernet address in the config file causes that line
+to be invalidated).
+.Pp
+The following signals have the specified effect when sent to the server
+process using the
+.Xr kill 1
+command:
+.Bl -tag -width SIGUSR1 -offset -compact
+.It SIGHUP
+Drop all active connections and reconfigure.
+.It SIGUSR1
+Turn on debugging, do nothing if already on.
+.It SIGUSR2
+Turn off debugging, do nothing if already off.
+.El
+.Sh "FILES"
+.Bl -tag -width /usr/libexec/rbootd -compact
+.It /dev/bpf#
+packet-filter device
+.It /etc/rbootd.conf
+configuration file
+.It /tmp/rbootd.dbg
+debug output
+.It /usr/mdec/rbootd
+directory containing boot files
+.It /var/run/rbootd.pid
+process id
+.El
+.Sh SEE ALSO
+.Xr kill 1 ,
+.Xr socket 2 ,
+.Xr signal 3 ,
+.Xr syslog 3 ,
+.Xr rmp 4
+.Sh BUGS
+If multiple servers are started on the same interface, each will receive
+and respond to the same boot packets.
diff --git a/rbootd.tproj/rbootd.c b/rbootd.tproj/rbootd.c
new file mode 100644 (file)
index 0000000..cf661b2
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)rbootd.c    8.2 (Berkeley) 2/22/94
+ *
+ * Utah $Hdr: rbootd.c 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rbootd.c   8.2 (Berkeley) 2/22/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "defs.h"
+
+
+/* fd mask macros (backward compatibility with 4.2BSD) */
+#ifndef        FD_SET
+#ifdef notdef
+typedef        struct fd_set {         /* this should already be in 4.2 */
+       int fds_bits[1];
+} fd_set;
+#endif
+#define        FD_ZERO(p)      ((p)->fds_bits[0] = 0)
+#define        FD_SET(n, p)    ((p)->fds_bits[0] |= (1 << (n)))
+#define        FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1 << (n)))
+#define        FD_ISSET(n, p)  ((p)->fds_bits[0] & (1 << (n)))
+#endif
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int c, fd, omask, maxfds;
+       fd_set rset;
+
+       /*
+        *  Find what name we are running under.
+        */
+       ProgName = (ProgName = rindex(argv[0],'/')) ? ++ProgName : *argv;
+
+       /*
+        *  Close any open file descriptors.
+        *  Temporarily leave stdin & stdout open for `-d',
+        *  and stderr open for any pre-syslog error messages.
+        */
+       {
+               int i, nfds = getdtablesize();
+
+               for (i = 0; i < nfds; i++)
+                       if (i != fileno(stdin) && i != fileno(stdout) &&
+                           i != fileno(stderr))
+                               (void) close(i);
+       }
+
+       /*
+        *  Parse any arguments.
+        */
+       while ((c = getopt(argc, argv, "adi:")) != EOF)
+               switch(c) {
+                   case 'a':
+                       BootAny++;
+                       break;
+                   case 'd':
+                       DebugFlg++;
+                       break;
+                   case 'i':
+                       IntfName = optarg;
+                       break;
+               }
+       for (; optind < argc; optind++) {
+               if (ConfigFile == NULL)
+                       ConfigFile = argv[optind];
+               else {
+                       fprintf(stderr,
+                               "%s: too many config files (`%s' ignored)\n",
+                               ProgName, argv[optind]);
+               }
+       }
+
+       if (ConfigFile == NULL)                 /* use default config file */
+               ConfigFile = DfltConfig;
+
+       if (DebugFlg) {
+               DbgFp = stdout;                         /* output to stdout */
+
+               (void) signal(SIGUSR1, SIG_IGN);        /* dont muck w/DbgFp */
+               (void) signal(SIGUSR2, SIG_IGN);
+       } else {
+               (void) fclose(stdin);                   /* dont need these */
+               (void) fclose(stdout);
+
+               /*
+                *  Fork off a child to do the work & exit.
+                */
+               switch(fork()) {
+                       case -1:        /* fork failed */
+                               fprintf(stderr, "%s: ", ProgName);
+                               perror("fork");
+                               Exit(0);
+                       case 0:         /* this is the CHILD */
+                               break;
+                       default:        /* this is the PARENT */
+                               _exit(0);
+               }
+
+               /*
+                *  Try to disassociate from the current tty.
+                */
+               {
+                       char *devtty = "/dev/tty";
+                       int i;
+
+                       if ((i = open(devtty, O_RDWR)) < 0) {
+                               /* probably already disassociated */
+                               if (setpgrp(0, 0) < 0) {
+                                       fprintf(stderr, "%s: ", ProgName);
+                                       perror("setpgrp");
+                               }
+                       } else {
+                               if (ioctl(i, (u_long)TIOCNOTTY, (char *)0) < 0){
+                                       fprintf(stderr, "%s: ", ProgName);
+                                       perror("ioctl");
+                               }
+                               (void) close(i);
+                       }
+               }
+
+               (void) signal(SIGUSR1, DebugOn);
+               (void) signal(SIGUSR2, DebugOff);
+       }
+
+       (void) fclose(stderr);          /* finished with it */
+
+#ifdef SYSLOG4_2
+       openlog(ProgName, LOG_PID);
+#else
+       openlog(ProgName, LOG_PID, LOG_DAEMON);
+#endif
+
+       /*
+        *  If no interface was specified, get one now.
+        *
+        *  This is convoluted because we want to get the default interface
+        *  name for the syslog("restarted") message.  If BpfGetIntfName()
+        *  runs into an error, it will return a syslog-able error message
+        *  (in `errmsg') which will be displayed here.
+        */
+       if (IntfName == NULL) {
+               char *errmsg;
+
+               if ((IntfName = BpfGetIntfName(&errmsg)) == NULL) {
+                       syslog(LOG_NOTICE, "restarted (??)");
+                       syslog(LOG_ERR, errmsg);
+                       Exit(0);
+               }
+       }
+
+       syslog(LOG_NOTICE, "restarted (%s)", IntfName);
+
+       (void) signal(SIGHUP, ReConfig);
+       (void) signal(SIGINT, Exit);
+       (void) signal(SIGTERM, Exit);
+
+       /*
+        *  Grab our host name and pid.
+        */
+       if (gethostname(MyHost, MAXHOSTNAMELEN) < 0) {
+               syslog(LOG_ERR, "gethostname: %m");
+               Exit(0);
+       }
+       MyHost[MAXHOSTNAMELEN] = '\0';
+
+       MyPid = getpid();
+
+       /*
+        *  Write proc's pid to a file.
+        */
+       {
+               FILE *fp;
+
+               if ((fp = fopen(PidFile, "w")) != NULL) {
+                       (void) fprintf(fp, "%d\n", MyPid);
+                       (void) fclose(fp);
+               } else {
+                       syslog(LOG_WARNING, "fopen: failed (%s)", PidFile);
+               }
+       }
+
+       /*
+        *  All boot files are relative to the boot directory, we might
+        *  as well chdir() there to make life easier.
+        */
+       if (chdir(BootDir) < 0) {
+               syslog(LOG_ERR, "chdir: %m (%s)", BootDir);
+               Exit(0);
+       }
+
+       /*
+        *  Initial configuration.
+        */
+       omask = sigblock(sigmask(SIGHUP));      /* prevent reconfig's */
+       if (GetBootFiles() == 0)                /* get list of boot files */
+               Exit(0);
+       if (ParseConfig() == 0)                 /* parse config file */
+               Exit(0);
+
+       /*
+        *  Open and initialize a BPF device for the appropriate interface.
+        *  If an error is encountered, a message is displayed and Exit()
+        *  is called.
+        */
+       fd = BpfOpen();
+
+       (void) sigsetmask(omask);               /* allow reconfig's */
+
+       /*
+        *  Main loop: receive a packet, determine where it came from,
+        *  and if we service this host, call routine to handle request.
+        */
+       maxfds = fd + 1;
+       FD_ZERO(&rset);
+       FD_SET(fd, &rset);
+       for (;;) {
+               struct timeval timeout;
+               fd_set r;
+               int nsel;
+
+               r = rset;
+
+               if (RmpConns == NULL) {         /* timeout isnt necessary */
+                       nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0,
+                                     (struct timeval *)0);
+               } else {
+                       timeout.tv_sec = RMP_TIMEOUT;
+                       timeout.tv_usec = 0;
+                       nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0,
+                                     &timeout);
+               }
+
+               if (nsel < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       syslog(LOG_ERR, "select: %m");
+                       Exit(0);
+               } else if (nsel == 0) {         /* timeout */
+                       DoTimeout();                    /* clear stale conns */
+                       continue;
+               }
+
+               if (FD_ISSET(fd, &r)) {
+                       RMPCONN rconn;
+                       CLIENT *client, *FindClient();
+                       int doread = 1;
+
+                       while (BpfRead(&rconn, doread)) {
+                               doread = 0;
+
+                               if (DbgFp != NULL)      /* display packet */
+                                       DispPkt(&rconn,DIR_RCVD);
+
+                               omask = sigblock(sigmask(SIGHUP));
+
+                               /*
+                                *  If we do not restrict service, set the
+                                *  client to NULL (ProcessPacket() handles
+                                *  this).  Otherwise, check that we can
+                                *  service this host; if not, log a message
+                                *  and ignore the packet.
+                                */
+                               if (BootAny) {
+                                       client = NULL;
+                               } else if ((client=FindClient(&rconn))==NULL) {
+                                       syslog(LOG_INFO,
+                                              "%s: boot packet ignored",
+                                              EnetStr(&rconn));
+                                       (void) sigsetmask(omask);
+                                       continue;
+                               }
+
+                               ProcessPacket(&rconn,client);
+
+                               (void) sigsetmask(omask);
+                       }
+               }
+       }
+}
+
+/*
+**  DoTimeout -- Free any connections that have timed out.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - Timed out connections in `RmpConns' will be freed.
+*/
+void
+DoTimeout()
+{
+       register RMPCONN *rtmp;
+       struct timeval now;
+
+       (void) gettimeofday(&now, (struct timezone *)0);
+
+       /*
+        *  For each active connection, if RMP_TIMEOUT seconds have passed
+        *  since the last packet was sent, delete the connection.
+        */
+       for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
+               if ((rtmp->tstamp.tv_sec + RMP_TIMEOUT) < now.tv_sec) {
+                       syslog(LOG_WARNING, "%s: connection timed out (%u)",
+                              EnetStr(rtmp), rtmp->rmp.r_type);
+                       RemoveConn(rtmp);
+               }
+}
+
+/*
+**  FindClient -- Find client associated with a packet.
+**
+**     Parameters:
+**             rconn - the new packet. 
+**
+**     Returns:
+**             Pointer to client info if found, NULL otherwise.
+**
+**     Side Effects:
+**             None.
+**
+**     Warnings:
+**             - This routine must be called with SIGHUP blocked since
+**               a reconfigure can invalidate the information returned.
+*/
+
+CLIENT *
+FindClient(rconn)
+       register RMPCONN *rconn;
+{
+       register CLIENT *ctmp;
+
+       for (ctmp = Clients; ctmp != NULL; ctmp = ctmp->next)
+               if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
+                        (char *)&ctmp->addr[0], RMP_ADDRLEN) == 0)
+                       break;
+
+       return(ctmp);
+}
+
+/*
+**  Exit -- Log an error message and exit.
+**
+**     Parameters:
+**             sig - caught signal (or zero if not dying on a signal).
+**
+**     Returns:
+**             Does not return.
+**
+**     Side Effects:
+**             - This process ceases to exist.
+*/
+void
+Exit(sig)
+       int sig;
+{
+       if (sig > 0)
+               syslog(LOG_ERR, "going down on signal %d", sig);
+       else
+               syslog(LOG_ERR, "going down with fatal error");
+       BpfClose();
+       exit(1);
+}
+
+/*
+**  ReConfig -- Get new list of boot files and reread config files.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - All active connections are dropped.
+**             - List of boot-able files is changed.
+**             - List of clients is changed.
+**
+**     Warnings:
+**             - This routine must be called with SIGHUP blocked.
+*/
+void
+ReConfig(signo)
+       int signo;
+{
+       syslog(LOG_NOTICE, "reconfiguring boot server");
+
+       FreeConns();
+
+       if (GetBootFiles() == 0)
+               Exit(0);
+
+       if (ParseConfig() == 0)
+               Exit(0);
+}
+
+/*
+**  DebugOff -- Turn off debugging.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - Debug file is closed.
+*/
+void
+DebugOff(signo)
+       int signo;
+{
+       if (DbgFp != NULL)
+               (void) fclose(DbgFp);
+
+       DbgFp = NULL;
+}
+
+/*
+**  DebugOn -- Turn on debugging.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - Debug file is opened/truncated if not already opened,
+**               otherwise do nothing.
+*/
+void
+DebugOn(signo)
+       int signo;
+{
+       if (DbgFp == NULL) {
+               if ((DbgFp = fopen(DbgFile, "w")) == NULL)
+                       syslog(LOG_ERR, "can't open debug file (%s)", DbgFile);
+       }
+}
diff --git a/rbootd.tproj/rmp.h b/rbootd.tproj/rmp.h
new file mode 100644 (file)
index 0000000..31b9440
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)rmp.h       8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: rmp.h 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+/*
+ *  Define MIN/MAX sizes of RMP (ethernet) packet.
+ *  For ease of computation, the 4 octet CRC field is not included.
+ *
+ *  MCLBYTES is for bpfwrite(); it is adamant about using a cluster.
+ */
+
+#define        RMP_MAX_PACKET  MIN(1514,MCLBYTES)
+#define        RMP_MIN_PACKET  60
+
+/*
+ *  Define RMP/Ethernet Multicast address (9:0:9:0:0:4) and its length.
+ */
+#define        RMP_ADDR        { 0x9, 0x0, 0x9, 0x0, 0x0, 0x4 }
+#define        RMP_ADDRLEN     6
+
+/*
+ *  Define IEEE802.2 (Logical Link Control) information.
+ */
+#define        IEEE_DSAP_HP    0xF8    /* Destination Service Access Point */
+#define        IEEE_SSAP_HP    0xF8    /* Source Service Access Point */
+#define        IEEE_CNTL_HP    0x0300  /* Type 1 / I format control information */
+
+#define        HPEXT_DXSAP     0x608   /* HP Destination Service Access Point */
+#define        HPEXT_SXSAP     0x609   /* HP Source Service Access Point */
+
+/*
+ *  802.3-style "Ethernet" header.
+ */
+
+struct hp_hdr {
+       u_char  daddr[RMP_ADDRLEN];
+       u_char  saddr[RMP_ADDRLEN];
+       u_short len;
+};
+
+/*
+ * HP uses 802.2 LLC with their own local extensions.  This struct makes
+ * sence out of this data (encapsulated in the above 802.3 packet).
+ */
+
+struct hp_llc {
+       u_char  dsap;           /* 802.2 DSAP */
+       u_char  ssap;           /* 802.2 SSAP */
+       u_short cntrl;          /* 802.2 control field */
+       u_short filler;         /* HP filler (must be zero) */
+       u_short dxsap;          /* HP extended DSAP */
+       u_short sxsap;          /* HP extended SSAP */
+};
diff --git a/rbootd.tproj/rmp_var.h b/rbootd.tproj/rmp_var.h
new file mode 100644 (file)
index 0000000..adecc85
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)rmp_var.h   8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: rmp_var.h 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+/*
+ *  Possible values for "rmp_type" fields.
+ */
+
+#define        RMP_BOOT_REQ    1       /* boot request packet */
+#define        RMP_BOOT_REPL   129     /* boot reply packet */
+#define        RMP_READ_REQ    2       /* read request packet */
+#define        RMP_READ_REPL   130     /* read reply packet */
+#define        RMP_BOOT_DONE   3       /* boot complete packet */
+
+/*
+ *  Useful constants.
+ */
+
+#define RMP_VERSION    2       /* protocol version */
+#define RMP_TIMEOUT    600     /* timeout connection after ten minutes */
+#define        RMP_PROBESID    0xffff  /* session ID for probes */
+#define        RMP_HOSTLEN     13      /* max length of server's name */
+#define        RMP_MACHLEN     20      /* length of machine type field */
+
+/*
+ *  RMP error codes
+ */
+
+#define        RMP_E_OKAY      0
+#define        RMP_E_EOF       2       /* read reply: returned end of file */
+#define        RMP_E_ABORT     3       /* abort operation */
+#define        RMP_E_BUSY      4       /* boot reply: server busy */
+#define        RMP_E_TIMEOUT   5       /* lengthen time out (not implemented) */
+#define        RMP_E_NOFILE    16      /* boot reply: file does not exist */
+#define RMP_E_OPENFILE 17      /* boot reply: file open failed */
+#define        RMP_E_NODFLT    18      /* boot reply: default file does not exist */
+#define RMP_E_OPENDFLT 19      /* boot reply: default file open failed */
+#define        RMP_E_BADSID    25      /* read reply: bad session ID */
+#define RMP_E_BADPACKET        27      /* Bad packet detected */
+
+/*
+ *  RMPDATALEN is the maximum number of data octets that can be stuffed
+ *  into an RMP packet.  This excludes the 802.2 LLC w/HP extensions.
+ */
+#define RMPDATALEN     (RMP_MAX_PACKET - (sizeof(struct hp_hdr) + \
+                                          sizeof(struct hp_llc)))
+
+/*
+ *  Define sizes of packets we send.  Boot and Read replies are variable
+ *  in length depending on the length of `s'.
+ *
+ *  Also, define how much space `restofpkt' can take up for outgoing
+ *  Boot and Read replies.  Boot Request packets are effectively
+ *  limited to 255 bytes due to the preceding 1-byte length field.
+ */
+
+#define        RMPBOOTSIZE(s)  (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
+                        sizeof(struct rmp_boot_repl) + s - sizeof(restofpkt))
+#define        RMPREADSIZE(s)  (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
+                        sizeof(struct rmp_read_repl) + s - sizeof(restofpkt) \
+                        - sizeof(u_char))
+#define        RMPDONESIZE     (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
+                        sizeof(struct rmp_boot_done))
+#define        RMPBOOTDATA     255
+#define        RMPREADDATA     (RMPDATALEN - \
+                        (2*sizeof(u_char)+sizeof(u_short)+sizeof(u_word)))
+
+/*
+ * This protocol defines some field sizes as "rest of ethernet packet".
+ * There is no easy way to specify this in C, so we use a one character
+ * field to denote it, and index past it to the end of the packet.
+ */
+
+typedef char   restofpkt;
+
+/*
+ * Due to the RMP packet layout, we'll run into alignment problems
+ * on machines that cant access words on half-word boundaries.  If
+ * you know that your machine does not suffer from this problem,
+ * add it to the hp300 #define below.
+ *
+ * The following macros are used to deal with this problem:
+ *     WORDZE(w)       Return True if u_word `w' is zero, False otherwise.
+ *     ZEROWORD(w)     Set u_word `w' to zero.
+ *     COPYWORD(w1,w2) Copy u_word `w1' to `w2'.
+ *     GETWORD(w,i)    Copy u_word `w' into int `i'.
+ *     PUTWORD(i,w)    Copy int `i' into u_word `w'.
+ *
+ * N.B. We do not support little endian alignment-challenged machines.
+ */
+#if defined(vax) || defined(tahoe) || defined(hp300)
+
+typedef        u_int           u_word;
+
+#define        WORDZE(w)       ((w) == 0)
+#define        ZEROWORD(w)     (w) = 0
+#define        COPYWORD(w1,w2) (w2) = (w1)
+#define        GETWORD(w, i)   (i) = (w)
+#define        PUTWORD(i, w)   (w) = (i)
+
+#else
+
+#define        _WORD_HIGHPART  0       /* XXX: assume Big Endian for now */
+#define        _WORD_LOWPART   1
+
+typedef        struct _uword { u_short val[2]; }       u_word;
+
+#define        WORDZE(w) \
+       ((w.val[_WORD_HIGHPART] == 0) && (w.val[_WORD_LOWPART] == 0))
+#define        ZEROWORD(w) \
+       (w).val[_WORD_HIGHPART] = (w).val[_WORD_LOWPART] = 0
+#define        COPYWORD(w1, w2) \
+       { (w2).val[_WORD_HIGHPART] = (w1).val[_WORD_HIGHPART]; \
+         (w2).val[_WORD_LOWPART] = (w1).val[_WORD_LOWPART]; \
+       }
+#define        GETWORD(w, i) \
+       (i) = (((u_int)(w).val[_WORD_HIGHPART]) << 16) | (w).val[_WORD_LOWPART]
+#define        PUTWORD(i, w) \
+       { (w).val[_WORD_HIGHPART] = (u_short) (((i) >> 16) & 0xffff); \
+         (w).val[_WORD_LOWPART] = (u_short) (i & 0xffff); \
+       }
+
+#endif
+
+/*
+ * Packet structures.
+ */
+
+struct rmp_raw {               /* generic RMP packet */
+       u_char  rmp_type;               /* packet type */
+       u_char  rmp_rawdata[RMPDATALEN-1];
+};
+
+struct rmp_boot_req {          /* boot request */
+       u_char  rmp_type;               /* packet type (RMP_BOOT_REQ) */
+       u_char  rmp_retcode;            /* return code (0) */
+       u_word  rmp_seqno;              /* sequence number (real time clock) */
+       u_short rmp_session;            /* session id (normally 0) */
+       u_short rmp_version;            /* protocol version (RMP_VERSION) */
+       char    rmp_machtype[RMP_MACHLEN];      /* machine type */
+       u_char  rmp_flnmsize;           /* length of rmp_flnm */
+       restofpkt rmp_flnm;             /* name of file to be read */
+};
+
+struct rmp_boot_repl {         /* boot reply */
+       u_char  rmp_type;               /* packet type (RMP_BOOT_REPL) */
+       u_char  rmp_retcode;            /* return code (normally 0) */
+       u_word  rmp_seqno;              /* sequence number (from boot req) */
+       u_short rmp_session;            /* session id (generated) */
+       u_short rmp_version;            /* protocol version (RMP_VERSION) */
+       u_char  rmp_flnmsize;           /* length of rmp_flnm */
+       restofpkt rmp_flnm;             /* name of file (from boot req) */
+};
+
+struct rmp_read_req {          /* read request */
+       u_char  rmp_type;               /* packet type (RMP_READ_REQ) */
+       u_char  rmp_retcode;            /* return code (0) */
+       u_word  rmp_offset;             /* file relative byte offset */
+       u_short rmp_session;            /* session id (from boot repl) */
+       u_short rmp_size;               /* max no of bytes to send */
+};
+
+struct rmp_read_repl {         /* read reply */
+       u_char  rmp_type;               /* packet type (RMP_READ_REPL) */
+       u_char  rmp_retcode;            /* return code (normally 0) */
+       u_word  rmp_offset;             /* byte offset (from read req) */
+       u_short rmp_session;            /* session id (from read req) */
+       restofpkt rmp_data;             /* data (max size from read req) */
+       u_char  rmp_unused;             /* padding to 16-bit boundary */
+};
+
+struct rmp_boot_done {         /* boot complete */
+       u_char  rmp_type;               /* packet type (RMP_BOOT_DONE) */
+       u_char  rmp_retcode;            /* return code (0) */
+       u_word  rmp_unused;             /* not used (0) */
+       u_short rmp_session;            /* session id (from read repl) */
+};
+
+struct rmp_packet {
+       struct hp_hdr hp_hdr;
+       struct hp_llc hp_llc;
+       union {
+               struct rmp_boot_req     rmp_brq;        /* boot request */
+               struct rmp_boot_repl    rmp_brpl;       /* boot reply */
+               struct rmp_read_req     rmp_rrq;        /* read request */
+               struct rmp_read_repl    rmp_rrpl;       /* read reply */
+               struct rmp_boot_done    rmp_done;       /* boot complete */
+               struct rmp_raw          rmp_raw;        /* raw data */
+       } rmp_proto;
+};
+
+/*
+ *  Make life easier...
+ */
+
+#define        r_type  rmp_proto.rmp_raw.rmp_type
+#define        r_data  rmp_proto.rmp_raw.rmp_data
+#define        r_brq   rmp_proto.rmp_brq
+#define        r_brpl  rmp_proto.rmp_brpl
+#define        r_rrq   rmp_proto.rmp_rrq
+#define        r_rrpl  rmp_proto.rmp_rrpl
+#define        r_done  rmp_proto.rmp_done
diff --git a/rbootd.tproj/rmpproto.c b/rbootd.tproj/rmpproto.c
new file mode 100644 (file)
index 0000000..d8f676c
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)rmpproto.c  8.1 (Berkeley) 6/4/93
+ *
+ * Utah $Hdr: rmpproto.c 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "defs.h"
+
+/*
+**  ProcessPacket -- determine packet type and do what's required.
+**
+**     An RMP BOOT packet has been received.  Look at the type field
+**     and process Boot Requests, Read Requests, and Boot Complete
+**     packets.  Any other type will be dropped with a warning msg.
+**
+**     Parameters:
+**             rconn - the new connection
+**             client - list of files available to this host
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - If this is a valid boot request, it will be added to
+**               the linked list of outstanding requests (RmpConns).
+**             - If this is a valid boot complete, its associated
+**               entry in RmpConns will be deleted.
+**             - Also, unless we run out of memory, a reply will be
+**               sent to the host that sent the packet.
+*/
+void
+ProcessPacket(rconn, client)
+       RMPCONN *rconn;
+       CLIENT *client;
+{
+       struct rmp_packet *rmp;
+       RMPCONN *rconnout;
+
+       rmp = &rconn->rmp;              /* cache pointer to RMP packet */
+
+       switch(rmp->r_type) {           /* do what we came here to do */
+               case RMP_BOOT_REQ:              /* boot request */
+                       if ((rconnout = NewConn(rconn)) == NULL)
+                               return;
+
+                       /*
+                        *  If the Session ID is 0xffff, this is a "probe"
+                        *  packet and we do not want to add the connection
+                        *  to the linked list of active connections.  There
+                        *  are two types of probe packets, if the Sequence
+                        *  Number is 0 they want to know our host name, o/w
+                        *  they want the name of the file associated with
+                        *  the number spec'd by the Sequence Number.
+                        *
+                        *  If this is an actual boot request, open the file
+                        *  and send a reply.  If SendBootRepl() does not
+                        *  return 0, add the connection to the linked list
+                        *  of active connections, otherwise delete it since
+                        *  an error was encountered.
+                        */
+                       if (rmp->r_brq.rmp_session == RMP_PROBESID) {
+                               if (WORDZE(rmp->r_brq.rmp_seqno))
+                                       (void) SendServerID(rconnout);
+                               else
+                                       (void) SendFileNo(rmp, rconnout,
+                                                         client? client->files:
+                                                                 BootFiles);
+                               FreeConn(rconnout);
+                       } else {
+                               if (SendBootRepl(rmp, rconnout,
+                                   client? client->files: BootFiles))
+                                       AddConn(rconnout);
+                               else
+                                       FreeConn(rconnout);
+                       }
+                       break;
+
+               case RMP_BOOT_REPL:             /* boot reply (not valid) */
+                       syslog(LOG_WARNING, "%s: sent a boot reply",
+                              EnetStr(rconn));
+                       break;
+
+               case RMP_READ_REQ:              /* read request */
+                       /*
+                        *  Send a portion of the boot file.
+                        */
+                       (void) SendReadRepl(rconn);
+                       break;
+
+               case RMP_READ_REPL:             /* read reply (not valid) */
+                       syslog(LOG_WARNING, "%s: sent a read reply",
+                              EnetStr(rconn));
+                       break;
+
+               case RMP_BOOT_DONE:             /* boot complete */
+                       /*
+                        *  Remove the entry from the linked list of active
+                        *  connections.
+                        */
+                       (void) BootDone(rconn);
+                       break;
+
+               default:                        /* unknown RMP packet type */
+                       syslog(LOG_WARNING, "%s: unknown packet type (%u)",
+                              EnetStr(rconn), rmp->r_type);
+       }
+}
+
+/*
+**  SendServerID -- send our host name to who ever requested it.
+**
+**     Parameters:
+**             rconn - the reply packet to be formatted.
+**
+**     Returns:
+**             1 on success, 0 on failure.
+**
+**     Side Effects:
+**             none.
+*/
+int
+SendServerID(rconn)
+       RMPCONN *rconn;
+{
+       register struct rmp_packet *rpl;
+       register char *src, *dst;
+       register u_char *size;
+
+       rpl = &rconn->rmp;                      /* cache ptr to RMP packet */
+
+       /*
+        *  Set up assorted fields in reply packet.
+        */
+       rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
+       rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
+       ZEROWORD(rpl->r_brpl.rmp_seqno);
+       rpl->r_brpl.rmp_session = 0;
+       rpl->r_brpl.rmp_version = RMP_VERSION;
+
+       size = &rpl->r_brpl.rmp_flnmsize;       /* ptr to length of host name */
+
+       /*
+        *  Copy our host name into the reply packet incrementing the
+        *  length as we go.  Stop at RMP_HOSTLEN or the first dot.
+        */
+       src = MyHost;
+       dst = (char *) &rpl->r_brpl.rmp_flnm;
+       for (*size = 0; *size < RMP_HOSTLEN; (*size)++) {
+               if (*src == '.' || *src == '\0')
+                       break;
+               *dst++ = *src++;
+       }
+
+       rconn->rmplen = RMPBOOTSIZE(*size);     /* set packet length */
+
+       return(SendPacket(rconn));              /* send packet */
+}
+
+/*
+**  SendFileNo -- send the name of a bootable file to the requester.
+**
+**     Parameters:
+**             req - RMP BOOT packet containing the request.
+**             rconn - the reply packet to be formatted.
+**             filelist - list of files available to the requester.
+**
+**     Returns:
+**             1 on success, 0 on failure.
+**
+**     Side Effects:
+**             none.
+*/
+int
+SendFileNo(req, rconn, filelist)
+       struct rmp_packet *req;
+       RMPCONN *rconn;
+       char *filelist[];
+{
+       register struct rmp_packet *rpl;
+       register char *src, *dst;
+       register u_char *size, i;
+
+       GETWORD(req->r_brpl.rmp_seqno, i);      /* SeqNo is really FileNo */
+       rpl = &rconn->rmp;                      /* cache ptr to RMP packet */
+
+       /*
+        *  Set up assorted fields in reply packet.
+        */
+       rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
+       PUTWORD(i, rpl->r_brpl.rmp_seqno);
+       i--;
+       rpl->r_brpl.rmp_session = 0;
+       rpl->r_brpl.rmp_version = RMP_VERSION;
+
+       size = &rpl->r_brpl.rmp_flnmsize;       /* ptr to length of filename */
+       *size = 0;                              /* init length to zero */
+
+       /*
+        *  Copy the file name into the reply packet incrementing the
+        *  length as we go.  Stop at end of string or when RMPBOOTDATA
+        *  characters have been copied.  Also, set return code to
+        *  indicate success or "no more files".
+        */
+       if (i < C_MAXFILE && filelist[i] != NULL) {
+               src = filelist[i];
+               dst = (char *)&rpl->r_brpl.rmp_flnm;
+               for (; *src && *size < RMPBOOTDATA; (*size)++) {
+                       if (*src == '\0')
+                               break;
+                       *dst++ = *src++;
+               }
+               rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
+       } else
+               rpl->r_brpl.rmp_retcode = RMP_E_NODFLT;
+
+       rconn->rmplen = RMPBOOTSIZE(*size);     /* set packet length */
+
+       return(SendPacket(rconn));              /* send packet */
+}
+
+/*
+**  SendBootRepl -- open boot file and respond to boot request.
+**
+**     Parameters:
+**             req - RMP BOOT packet containing the request.
+**             rconn - the reply packet to be formatted.
+**             filelist - list of files available to the requester.
+**
+**     Returns:
+**             1 on success, 0 on failure.
+**
+**     Side Effects:
+**             none.
+*/
+int
+SendBootRepl(req, rconn, filelist)
+       struct rmp_packet *req;
+       RMPCONN *rconn;
+       char *filelist[];
+{
+       int retval;
+       char *filename, filepath[RMPBOOTDATA+1];
+       RMPCONN *oldconn;
+       register struct rmp_packet *rpl;
+       register char *src, *dst1, *dst2;
+       register u_char i;
+
+       /*
+        *  If another connection already exists, delete it since we
+        *  are obviously starting again.
+        */
+       if ((oldconn = FindConn(rconn)) != NULL) {
+               syslog(LOG_WARNING, "%s: dropping existing connection",
+                      EnetStr(oldconn));
+               RemoveConn(oldconn);
+       }
+
+       rpl = &rconn->rmp;                      /* cache ptr to RMP packet */
+
+       /*
+        *  Set up assorted fields in reply packet.
+        */
+       rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
+       COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno);
+       rpl->r_brpl.rmp_session = GenSessID();
+       rpl->r_brpl.rmp_version = RMP_VERSION;
+       rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize;
+
+       /*
+        *  Copy file name to `filepath' string, and into reply packet.
+        */
+       src = &req->r_brq.rmp_flnm;
+       dst1 = filepath;
+       dst2 = &rpl->r_brpl.rmp_flnm;
+       for (i = 0; i < req->r_brq.rmp_flnmsize; i++)
+               *dst1++ = *dst2++ = *src++;
+       *dst1 = '\0';
+
+       /*
+        *  If we are booting HP-UX machines, their secondary loader will
+        *  ask for files like "/hp-ux".  As a security measure, we do not
+        *  allow boot files to lay outside the boot directory (unless they
+        *  are purposely link'd out.  So, make `filename' become the path-
+        *  stripped file name and spoof the client into thinking that it
+        *  really got what it wanted.
+        */
+       filename = (filename = rindex(filepath,'/'))? ++filename: filepath;
+
+       /*
+        *  Check that this is a valid boot file name.
+        */
+       for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++)
+               if (STREQN(filename, filelist[i]))
+                       goto match;
+
+       /*
+        *  Invalid boot file name, set error and send reply packet.
+        */
+       rpl->r_brpl.rmp_retcode = RMP_E_NOFILE;
+       retval = 0;
+       goto sendpkt;
+
+match:
+       /*
+        *  This is a valid boot file.  Open the file and save the file
+        *  descriptor associated with this connection and set success
+        *  indication.  If the file couldnt be opened, set error:
+        *      "no such file or dir" - RMP_E_NOFILE
+        *      "file table overflow" - RMP_E_BUSY
+        *      "too many open files" - RMP_E_BUSY
+        *      anything else         - RMP_E_OPENFILE
+        */
+       if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) {
+               rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE:
+                       (errno == EMFILE || errno == ENFILE)? RMP_E_BUSY:
+                       RMP_E_OPENFILE;
+               retval = 0;
+       } else {
+               rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
+               retval = 1;
+       }
+
+sendpkt:
+       syslog(LOG_INFO, "%s: request to boot %s (%s)",
+              EnetStr(rconn), filename, retval? "granted": "denied");
+
+       rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize);
+
+       return (retval & SendPacket(rconn));
+}
+
+/*
+**  SendReadRepl -- send a portion of the boot file to the requester.
+**
+**     Parameters:
+**             rconn - the reply packet to be formatted.
+**
+**     Returns:
+**             1 on success, 0 on failure.
+**
+**     Side Effects:
+**             none.
+*/
+int
+SendReadRepl(rconn)
+       RMPCONN *rconn;
+{
+       int retval;
+       RMPCONN *oldconn;
+       register struct rmp_packet *rpl, *req;
+       register int size = 0;
+       int madeconn = 0;
+
+       /*
+        *  Find the old connection.  If one doesnt exist, create one only
+        *  to return the error code.
+        */
+       if ((oldconn = FindConn(rconn)) == NULL) {
+               if ((oldconn = NewConn(rconn)) == NULL)
+                       return(0);
+               syslog(LOG_ERR, "SendReadRepl: no active connection (%s)",
+                      EnetStr(rconn));
+               madeconn++;
+       }
+
+       req = &rconn->rmp;              /* cache ptr to request packet */
+       rpl = &oldconn->rmp;            /* cache ptr to reply packet */
+
+       if (madeconn) {                 /* no active connection above; abort */
+               rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
+               retval = 1;
+               goto sendpkt;
+       }
+
+       /*
+        *  Make sure Session ID's match.
+        */
+       if (req->r_rrq.rmp_session !=
+           ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:
+                                           rpl->r_rrpl.rmp_session)) {
+               syslog(LOG_ERR, "SendReadRepl: bad session id (%s)",
+                      EnetStr(rconn));
+               rpl->r_rrpl.rmp_retcode = RMP_E_BADSID;
+               retval = 1;
+               goto sendpkt;
+       }
+
+       /*
+        *  If the requester asks for more data than we can fit,
+        *  silently clamp the request size down to RMPREADDATA.
+        *
+        *  N.B. I do not know if this is "legal", however it seems
+        *  to work.  This is necessary for bpfwrite() on machines
+        *  with MCLBYTES less than 1514.
+        */
+       if (req->r_rrq.rmp_size > RMPREADDATA)
+               req->r_rrq.rmp_size = RMPREADDATA;
+
+       /*
+        *  Position read head on file according to info in request packet.
+        */
+       GETWORD(req->r_rrq.rmp_offset, size);
+       if (lseek(oldconn->bootfd, (off_t)size, L_SET) < 0) {
+               syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)",
+                      EnetStr(rconn));
+               rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
+               retval = 1;
+               goto sendpkt;
+       }
+
+       /*
+        *  Read data directly into reply packet.
+        */
+       if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data,
+                        (int) req->r_rrq.rmp_size)) <= 0) {
+               if (size < 0) {
+                       syslog(LOG_ERR, "SendReadRepl: read: %m (%s)",
+                              EnetStr(rconn));
+                       rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
+               } else {
+                       rpl->r_rrpl.rmp_retcode = RMP_E_EOF;
+               }
+               retval = 1;
+               goto sendpkt;
+       }
+
+       /*
+        *  Set success indication.
+        */
+       rpl->r_rrpl.rmp_retcode = RMP_E_OKAY;
+
+sendpkt:
+       /*
+        *  Set up assorted fields in reply packet.
+        */
+       rpl->r_rrpl.rmp_type = RMP_READ_REPL;
+       COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset);
+       rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session;
+
+       oldconn->rmplen = RMPREADSIZE(size);    /* set size of packet */
+
+       retval &= SendPacket(oldconn);          /* send packet */
+
+       if (madeconn)                           /* clean up after ourself */
+               FreeConn(oldconn);
+
+       return (retval);
+}
+
+/*
+**  BootDone -- free up memory allocated for a connection.
+**
+**     Parameters:
+**             rconn - incoming boot complete packet.
+**
+**     Returns:
+**             1 on success, 0 on failure.
+**
+**     Side Effects:
+**             none.
+*/
+int
+BootDone(rconn)
+       RMPCONN *rconn;
+{
+       RMPCONN *oldconn;
+       struct rmp_packet *rpl;
+
+       /*
+        *  If we cant find the connection, ignore the request.
+        */
+       if ((oldconn = FindConn(rconn)) == NULL) {
+               syslog(LOG_ERR, "BootDone: no existing connection (%s)",
+                      EnetStr(rconn));
+               return(0);
+       }
+
+       rpl = &oldconn->rmp;                    /* cache ptr to RMP packet */
+
+       /*
+        *  Make sure Session ID's match.
+        */
+       if (rconn->rmp.r_rrq.rmp_session !=
+           ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:
+                                           rpl->r_rrpl.rmp_session)) {
+               syslog(LOG_ERR, "BootDone: bad session id (%s)",
+                      EnetStr(rconn));
+               return(0);
+       }
+
+       RemoveConn(oldconn);                    /* remove connection */
+
+       syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn));
+
+       return(1);
+}
+
+/*
+**  SendPacket -- send an RMP packet to a remote host.
+**
+**     Parameters:
+**             rconn - packet to be sent.
+**
+**     Returns:
+**             1 on success, 0 on failure.
+**
+**     Side Effects:
+**             none.
+*/
+int
+SendPacket(rconn)
+       register RMPCONN *rconn;
+{
+       /*
+        *  Set Ethernet Destination address to Source (BPF and the enet
+        *  driver will take care of getting our source address set).
+        */
+       bcopy((char *)&rconn->rmp.hp_hdr.saddr[0],
+             (char *)&rconn->rmp.hp_hdr.daddr[0], RMP_ADDRLEN);
+       rconn->rmp.hp_hdr.len = rconn->rmplen - sizeof(struct hp_hdr);
+
+       /*
+        *  Reverse 802.2/HP Extended Source & Destination Access Pts.
+        */
+       rconn->rmp.hp_llc.dxsap = HPEXT_SXSAP;
+       rconn->rmp.hp_llc.sxsap = HPEXT_DXSAP;
+
+       /*
+        *  Last time this connection was active.
+        */
+       (void) gettimeofday(&rconn->tstamp, (struct timezone *)0);
+
+       if (DbgFp != NULL)                      /* display packet */
+               DispPkt(rconn,DIR_SENT);
+
+       /*
+        *  Send RMP packet to remote host.
+        */
+       return(BpfWrite(rconn));
+}
diff --git a/rbootd.tproj/utils.c b/rbootd.tproj/utils.c
new file mode 100644 (file)
index 0000000..7837471
--- /dev/null
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1992 The University of Utah and the Center
+ *     for Software Science (CSS).
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Center for Software Science of the University of Utah Computer
+ * Science Department.  CSS requests users of this software to return
+ * to css-dist@cs.utah.edu any improvements that they make and grant
+ * CSS redistribution rights.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)utils.c     8.2 (Berkeley) 2/22/94
+ *
+ * Utah $Hdr: utils.c 3.1 92/07/06$
+ * Author: Jeff Forys, University of Utah CSS
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)utils.c    8.2 (Berkeley) 2/22/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+#include "defs.h"
+
+/*
+**  DispPkt -- Display the contents of an RMPCONN packet.
+**
+**     Parameters:
+**             rconn - packet to be displayed.
+**             direct - direction packet is going (DIR_*).
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             None.
+*/
+void
+DispPkt(rconn, direct)
+       RMPCONN *rconn;
+       int direct;
+{
+       static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
+       static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
+
+       struct tm *tmp;
+       register struct rmp_packet *rmp;
+       int i, omask;
+       u_int t;
+
+       /*
+        *  Since we will be working with RmpConns as well as DbgFp, we
+        *  must block signals that can affect either.
+        */
+       omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
+
+       if (DbgFp == NULL) {                    /* sanity */
+               (void) sigsetmask(omask);
+               return;
+       }
+
+       /* display direction packet is going using '>>>' or '<<<' */
+       fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
+
+       /* display packet timestamp */
+       tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
+       fprintf(DbgFp, "%02d:%02d:%02d.%06ld   ", tmp->tm_hour, tmp->tm_min,
+               tmp->tm_sec, rconn->tstamp.tv_usec);
+
+       /* display src or dst addr and information about network interface */
+       fprintf(DbgFp, "Addr: %s   Intf: %s\n", EnetStr(rconn), IntfName);
+
+       rmp = &rconn->rmp;
+
+       /* display IEEE 802.2 Logical Link Control header */
+       (void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
+                      rmp->hp_llc.dsap, rmp->hp_llc.ssap, rmp->hp_llc.cntrl);
+
+       /* display HP extensions to 802.2 Logical Link Control header */
+       (void) fprintf(DbgFp, "\tHP Ext:    DXSAP:%x SXSAP:%x\n",
+                      rmp->hp_llc.dxsap, rmp->hp_llc.sxsap);
+
+       /*
+        *  Display information about RMP packet using type field to
+        *  determine what kind of packet this is.
+        */
+       switch(rmp->r_type) {
+               case RMP_BOOT_REQ:              /* boot request */
+                       (void) fprintf(DbgFp, "\tBoot Request:");
+                       GETWORD(rmp->r_brq.rmp_seqno, t);
+                       if (rmp->r_brq.rmp_session == RMP_PROBESID) {
+                               if (WORDZE(rmp->r_brq.rmp_seqno))
+                                       fputs(" (Send Server ID)", DbgFp);
+                               else
+                                       fprintf(DbgFp," (Send Filename #%u)",t);
+                       }
+                       (void) fputc('\n', DbgFp);
+                       (void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
+                               t, rmp->r_brq.rmp_session,
+                               rmp->r_brq.rmp_version);
+                       (void) fprintf(DbgFp, "\n\t\tMachine Type: ");
+                       for (i = 0; i < RMP_MACHLEN; i++)
+                               (void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
+                       DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
+                       break;
+               case RMP_BOOT_REPL:             /* boot reply */
+                       fprintf(DbgFp, "\tBoot Reply:\n");
+                       GETWORD(rmp->r_brpl.rmp_seqno, t);
+                       (void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
+                               t, rmp->r_brpl.rmp_session,
+                               rmp->r_brpl.rmp_version);
+                       DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
+                       break;
+               case RMP_READ_REQ:              /* read request */
+                       (void) fprintf(DbgFp, "\tRead Request:\n");
+                       GETWORD(rmp->r_rrq.rmp_offset, t);
+                       (void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
+                               t, rmp->r_rrq.rmp_session);
+                       (void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
+                               rmp->r_rrq.rmp_size);
+                       break;
+               case RMP_READ_REPL:             /* read reply */
+                       (void) fprintf(DbgFp, "\tRead Reply:\n");
+                       GETWORD(rmp->r_rrpl.rmp_offset, t);
+                       (void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
+                               t, rmp->r_rrpl.rmp_session);
+                       (void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
+                               rconn->rmplen - RMPREADSIZE(0));
+                       break;
+               case RMP_BOOT_DONE:             /* boot complete */
+                       (void) fprintf(DbgFp, "\tBoot Complete:\n");
+                       (void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
+                               rmp->r_done.rmp_retcode,
+                               rmp->r_done.rmp_session);
+                       break;
+               default:                        /* ??? */
+                       (void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
+                               rmp->r_type);
+       }
+       (void) fputc('\n', DbgFp);
+       (void) fflush(DbgFp);
+
+       (void) sigsetmask(omask);               /* reset old signal mask */
+}
+
+
+/*
+**  GetEtherAddr -- convert an RMP (Ethernet) address into a string.
+**
+**     An RMP BOOT packet has been received.  Look at the type field
+**     and process Boot Requests, Read Requests, and Boot Complete
+**     packets.  Any other type will be dropped with a warning msg.
+**
+**     Parameters:
+**             addr - array of RMP_ADDRLEN bytes.
+**
+**     Returns:
+**             Pointer to static string representation of `addr'.
+**
+**     Side Effects:
+**             None.
+**
+**     Warnings:
+**             - The return value points to a static buffer; it must
+**               be copied if it's to be saved.
+**             - For speed, we assume a u_char consists of 8 bits.
+*/
+char *
+GetEtherAddr(addr)
+       u_char *addr;
+{
+       static char Hex[] = "0123456789abcdef";
+       static char etherstr[RMP_ADDRLEN*3];
+       register int i;
+       register char *cp1, *cp2;
+
+       /*
+        *  For each byte in `addr', convert it to "<hexchar><hexchar>:".
+        *  The last byte does not get a trailing `:' appended.
+        */
+       i = 0;
+       cp1 = (char *)addr;
+       cp2 = etherstr;
+       for(;;) {
+               *cp2++ = Hex[*cp1 >> 4 & 0xf];
+               *cp2++ = Hex[*cp1++ & 0xf];
+               if (++i == RMP_ADDRLEN)
+                       break;
+               *cp2++ = ':';
+       }
+       *cp2 = '\0';
+
+       return(etherstr);
+}
+
+
+/*
+**  DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
+**
+**     Parameters:
+**             size - number of bytes to print.
+**             flnm - address of first byte.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - Characters are sent to `DbgFp'.
+*/
+void
+DspFlnm(size, flnm)
+       register u_int size;
+       register char *flnm;
+{
+       register int i;
+
+       (void) fprintf(DbgFp, "\n\t\tFile Name (%d): <", size);
+       for (i = 0; i < size; i++)
+               (void) fputc(*flnm++, DbgFp);
+       (void) fputs(">\n", DbgFp);
+}
+
+
+/*
+**  NewClient -- allocate memory for a new CLIENT.
+**
+**     Parameters:
+**             addr - RMP (Ethernet) address of new client.
+**
+**     Returns:
+**             Ptr to new CLIENT or NULL if we ran out of memory.
+**
+**     Side Effects:
+**             - Memory will be malloc'd for the new CLIENT.
+**             - If malloc() fails, a log message will be generated.
+*/
+CLIENT *
+NewClient(addr)
+       u_char *addr;
+{
+       CLIENT *ctmp;
+
+       if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
+               syslog(LOG_ERR, "NewClient: out of memory (%s)",
+                      GetEtherAddr(addr));
+               return(NULL);
+       }
+
+       bzero(ctmp, sizeof(CLIENT));
+       bcopy(addr, &ctmp->addr[0], RMP_ADDRLEN);
+       return(ctmp);
+}
+
+/*
+**  FreeClient -- free linked list of Clients.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - All malloc'd memory associated with the linked list of
+**               CLIENTS will be free'd; `Clients' will be set to NULL.
+**
+**     Warnings:
+**             - This routine must be called with SIGHUP blocked.
+*/
+void
+FreeClients()
+{
+       register CLIENT *ctmp;
+
+       while (Clients != NULL) {
+               ctmp = Clients;
+               Clients = Clients->next;
+               FreeClient(ctmp);
+       }
+}
+
+/*
+**  NewStr -- allocate memory for a character array.
+**
+**     Parameters:
+**             str - null terminated character array.
+**
+**     Returns:
+**             Ptr to new character array or NULL if we ran out of memory.
+**
+**     Side Effects:
+**             - Memory will be malloc'd for the new character array.
+**             - If malloc() fails, a log message will be generated.
+*/
+char *
+NewStr(str)
+       char *str;
+{
+       char *stmp;
+
+       if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
+               syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
+               return(NULL);
+       }
+
+       (void) strcpy(stmp, str);
+       return(stmp);
+}
+
+/*
+**  To save time, NewConn and FreeConn maintain a cache of one RMPCONN
+**  in `LastFree' (defined below).
+*/
+
+static RMPCONN *LastFree = NULL;
+
+/*
+**  NewConn -- allocate memory for a new RMPCONN connection.
+**
+**     Parameters:
+**             rconn - initialization template for new connection.
+**
+**     Returns:
+**             Ptr to new RMPCONN or NULL if we ran out of memory.
+**
+**     Side Effects:
+**             - Memory may be malloc'd for the new RMPCONN (if not cached).
+**             - If malloc() fails, a log message will be generated.
+*/
+RMPCONN *
+NewConn(rconn)
+       RMPCONN *rconn;
+{
+       RMPCONN *rtmp;
+
+       if (LastFree == NULL) {         /* nothing cached; make a new one */
+               if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
+                       syslog(LOG_ERR, "NewConn: out of memory (%s)",
+                              EnetStr(rconn));
+                       return(NULL);
+               }
+       } else {                        /* use the cached RMPCONN */
+               rtmp = LastFree;
+               LastFree = NULL;
+       }
+
+       /*
+        *  Copy template into `rtmp', init file descriptor to `-1' and
+        *  set ptr to next elem NULL.
+        */
+       bcopy((char *)rconn, (char *)rtmp, sizeof(RMPCONN));
+       rtmp->bootfd = -1;
+       rtmp->next = NULL;
+
+       return(rtmp);
+}
+
+/*
+**  FreeConn -- Free memory associated with an RMPCONN connection.
+**
+**     Parameters:
+**             rtmp - ptr to RMPCONN to be free'd.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - Memory associated with `rtmp' may be free'd (or cached).
+**             - File desc associated with `rtmp->bootfd' will be closed.
+*/
+void
+FreeConn(rtmp)
+       register RMPCONN *rtmp;
+{
+       /*
+        *  If the file descriptor is in use, close the file.
+        */
+       if (rtmp->bootfd >= 0) {
+               (void) close(rtmp->bootfd);
+               rtmp->bootfd = -1;
+       }
+
+       if (LastFree == NULL)           /* cache for next time */
+               rtmp = LastFree;
+       else                            /* already one cached; free this one */
+               free((char *)rtmp);
+}
+
+/*
+**  FreeConns -- free linked list of RMPCONN connections.
+**
+**     Parameters:
+**             None.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - All malloc'd memory associated with the linked list of
+**               connections will be free'd; `RmpConns' will be set to NULL.
+**             - If LastFree is != NULL, it too will be free'd & NULL'd.
+**
+**     Warnings:
+**             - This routine must be called with SIGHUP blocked.
+*/
+void
+FreeConns()
+{
+       register RMPCONN *rtmp;
+
+       while (RmpConns != NULL) {
+               rtmp = RmpConns;
+               RmpConns = RmpConns->next;
+               FreeConn(rtmp);
+       }
+
+       if (LastFree != NULL) {
+               free((char *)LastFree);
+               LastFree = NULL;
+       }
+}
+
+/*
+**  AddConn -- Add a connection to the linked list of connections.
+**
+**     Parameters:
+**             rconn - connection to be added.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - RmpConn will point to new connection.
+**
+**     Warnings:
+**             - This routine must be called with SIGHUP blocked.
+*/
+void
+AddConn(rconn)
+       register RMPCONN *rconn;
+{
+       if (RmpConns != NULL)
+               rconn->next = RmpConns;
+       RmpConns = rconn;
+}
+
+/*
+**  FindConn -- Find a connection in the linked list of connections.
+**
+**     We use the RMP (Ethernet) address as the basis for determining
+**     if this is the same connection.  According to the Remote Maint
+**     Protocol, we can only have one connection with any machine.
+**
+**     Parameters:
+**             rconn - connection to be found.
+**
+**     Returns:
+**             Matching connection from linked list or NULL if not found.
+**
+**     Side Effects:
+**             None.
+**
+**     Warnings:
+**             - This routine must be called with SIGHUP blocked.
+*/
+RMPCONN *
+FindConn(rconn)
+       register RMPCONN *rconn;
+{
+       register RMPCONN *rtmp;
+
+       for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
+               if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
+                        (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
+                       break;
+
+       return(rtmp);
+}
+
+/*
+**  RemoveConn -- Remove a connection from the linked list of connections.
+**
+**     Parameters:
+**             rconn - connection to be removed.
+**
+**     Returns:
+**             Nothing.
+**
+**     Side Effects:
+**             - If found, an RMPCONN will cease to exist and it will
+**               be removed from the linked list.
+**
+**     Warnings:
+**             - This routine must be called with SIGHUP blocked.
+*/
+void
+RemoveConn(rconn)
+       register RMPCONN *rconn;
+{
+       register RMPCONN *thisrconn, *lastrconn;
+
+       if (RmpConns == rconn) {                /* easy case */
+               RmpConns = RmpConns->next;
+               FreeConn(rconn);
+       } else {                                /* must traverse linked list */
+               lastrconn = RmpConns;                   /* set back ptr */
+               thisrconn = lastrconn->next;            /* set current ptr */
+               while (thisrconn != NULL) {
+                       if (rconn == thisrconn) {               /* found it */
+                               lastrconn->next = thisrconn->next;
+                               FreeConn(thisrconn);
+                               break;
+                       }
+                       lastrconn = thisrconn;
+                       thisrconn = thisrconn->next;
+               }
+       }
+}
diff --git a/rcp.tproj/Makefile b/rcp.tproj/Makefile
new file mode 100644 (file)
index 0000000..a35583a
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rcp
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h pathnames.h
+
+CFILES = rcp.c util.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            rcp.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /bin
+WINDOWS_INSTALLDIR = /bin
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rcp.tproj/Makefile.dist b/rcp.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..898f9a7
--- /dev/null
@@ -0,0 +1,13 @@
+#      @(#)Makefile    8.1 (Berkeley) 7/19/93
+
+PROG=  rcp
+SRCS=  rcp.c krcmd.c kcmd.c util.c
+CFLAGS+=-DKERBEROS -DCRYPT
+DPADD= ${LIBKRB} ${LIBDES}
+LDADD= -lkrb -ldes
+BINOWN=        root
+BINMODE=4555
+INSTALLFLAGS=-fschg
+.PATH: ${.CURDIR}/../../usr.bin/rlogin
+
+.include <bsd.prog.mk>
diff --git a/rcp.tproj/Makefile.postamble b/rcp.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..54c0935
--- /dev/null
@@ -0,0 +1,5 @@
+VPATH += :$(SRCROOT)$(SRCPATH)/../rlogin.tproj
+INSTALL_PERMISSIONS = 4555    # If set, 'install' chmod's executable to this
+
+after_install::
+       $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
diff --git a/rcp.tproj/Makefile.preamble b/rcp.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..8f3d6b7
--- /dev/null
@@ -0,0 +1,5 @@
+RLOGIN_CFILES = krcmd.c des_rw.c
+OTHER_OFILES = $(RLOGIN_CFILES:.c=.o)
+VPATH_PREAMBLE = ../rlogin.tproj:
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/rcp.tproj/PB.project b/rcp.tproj/PB.project
new file mode 100644 (file)
index 0000000..c2b93b6
--- /dev/null
@@ -0,0 +1,29 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (extern.h, pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (rcp.c, util.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, rcp.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = rcp; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = rcp; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rcp; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = rcp; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rcp.tproj/extern.h b/rcp.tproj/extern.h
new file mode 100644 (file)
index 0000000..706251f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)extern.h    8.1 (Berkeley) 5/31/93
+ */
+
+typedef struct {
+       int cnt;
+       char *buf;
+} BUF;
+
+extern int iamremote;
+
+BUF    *allocbuf __P((BUF *, int, int));
+char   *colon __P((char *));
+void    lostconn __P((int));
+void    nospace __P((void));
+int     okname __P((char *));
+void    run_err __P((const char *, ...));
+int     susystem __P((char *, int));
+void    verifydir __P((char *));
diff --git a/rcp.tproj/pathnames.h b/rcp.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..a93c4e6
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 5/31/93
+ */
+
+#include <paths.h>
+
+#define        _PATH_CP        "/bin/cp"
+#define        _PATH_RSH       "/usr/bin/rsh"
diff --git a/rcp.tproj/rcp.1 b/rcp.tproj/rcp.1
new file mode 100644 (file)
index 0000000..bff0a01
--- /dev/null
@@ -0,0 +1,159 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)rcp.1       8.1 (Berkeley) 5/31/93
+.\"
+.Dd May 31, 1993
+.Dt RCP 1
+.Os BSD 4.3r
+.Sh NAME
+.Nm rcp
+.Nd remote file copy
+.Sh SYNOPSIS
+.Nm rcp
+.Op Fl Kpx
+.Op Fl k Ar realm
+.Ar file1 file2
+.Nm rcp
+.Op Fl Kprx
+.Op Fl k Ar realm
+.Ar file ...
+.Ar directory
+.Sh DESCRIPTION
+.Nm Rcp
+copies files between machines.  Each
+.Ar file
+or
+.Ar directory
+argument is either a remote file name of the
+form ``rname@rhost:path'', or a local file name (containing no `:' characters,
+or a `/' before any `:'s).
+.Pp
+.Bl -tag -width flag
+.It Fl K
+The
+.Fl K
+option turns off all Kerberos authentication.
+.It Fl k
+The
+.Fl k
+option requests
+.Nm rcp
+to obtain tickets
+for the remote host in realm
+.Ar realm
+instead of the remote host's realm as determined by
+.Xr krb_realmofhost  3  .
+.It Fl p
+The
+.Fl p
+option causes
+.Nm rcp
+to attempt to preserve (duplicate) in its copies the modification
+times and modes of the source files, ignoring the
+.Ar umask  .
+By default, the mode and owner of
+.Ar file2
+are preserved if it already existed; otherwise the mode of the source file
+modified by the
+.Xr umask  2
+on the destination host is used.
+.It Fl r
+If any of the source files are directories,
+.Nm rcp
+copies each subtree rooted at that name; in this case
+the destination must be a directory.
+.It Fl x
+The
+.Fl x
+option turns on
+.Tn DES
+encryption for all data passed by
+.Nm rcp .
+This may impact response time and
+.Tn CPU
+utilization, but provides
+increased security.
+.El
+.Pp
+If
+.Ar path
+is not a full path name, it is interpreted relative to
+the login directory of the specified user
+.Ar ruser
+on
+.Ar rhost  ,
+or your current user name if no other remote user name is specified.
+A
+.Ar path
+on a remote host may be quoted (using \e, ", or \(aa)
+so that the metacharacters are interpreted remotely.
+.Pp
+.Nm Rcp
+does not prompt for passwords; it performs remote execution
+via
+.Xr rsh  1  ,
+and requires the same authorization.
+.Pp
+.Nm Rcp
+handles third party copies, where neither source nor target files
+are on the current machine.
+.Sh SEE ALSO
+.Xr cp 1 ,
+.Xr ftp 1 ,
+.Xr rsh 1 ,
+.Xr rlogin 1
+.Sh HISTORY
+The
+.Nm rcp
+command appeared in
+.Bx 4.2 .
+The version of
+.Nm rcp
+described here
+has been reimplemented with Kerberos in
+.Bx 4.3 Reno .
+.Sh BUGS
+Doesn't detect all cases where the target of a copy might
+be a file in cases where only a directory should be legal.
+.Pp
+Is confused by any output generated by commands in a
+.Pa \&.login ,
+.Pa \&.profile ,
+or
+.Pa \&.cshrc
+file on the remote host.
+.Pp
+The destination user and hostname may have to be specified as
+``rhost.rname'' when the destination machine is running the
+.Bx 4.2
+version of
+.Nm rcp  .
diff --git a/rcp.tproj/rcp.c b/rcp.tproj/rcp.c
new file mode 100644 (file)
index 0000000..579f328
--- /dev/null
@@ -0,0 +1,938 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1990, 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+#include "extern.h"
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+char   dst_realm_buf[REALM_SZ];
+char   *dest_realm = NULL;
+int    use_kerberos = 1;
+CREDENTIALS    cred;
+Key_schedule   schedule;
+extern char    *krb_realmofhost();
+#ifdef CRYPT
+int    doencrypt = 0;
+#define        OPTIONS "dfKk:prtx"
+#else
+#define        OPTIONS "dfKk:prt"
+#endif
+#else
+#define        OPTIONS "dfprt"
+#endif
+
+struct passwd *pwd;
+u_short        port;
+uid_t  userid;
+int errs, rem;
+int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+
+#define        CMDNEEDS        64
+char cmd[CMDNEEDS];            /* must hold "rcp -r -p -d\0" */
+
+#ifdef KERBEROS
+int     kerberos __P((char **, char *, char *, char *));
+void    oldw __P((const char *, ...));
+#endif
+int     response __P((void));
+void    rsource __P((char *, struct stat *));
+void    sink __P((int, char *[]));
+void    source __P((int, char *[]));
+void    tolocal __P((int, char *[]));
+void    toremote __P((char *, int, char *[]));
+void    usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct servent *sp;
+       int ch, fflag, tflag;
+       char *targ, *shell;
+
+       fflag = tflag = 0;
+       while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
+               switch(ch) {                    /* User-visible flags. */
+               case 'K':
+#ifdef KERBEROS
+                       use_kerberos = 0;
+#endif
+                       break;
+#ifdef KERBEROS
+               case 'k':
+                       dest_realm = dst_realm_buf;
+                       (void)strncpy(dst_realm_buf, optarg, REALM_SZ);
+                       break;
+#ifdef CRYPT
+               case 'x':
+                       doencrypt = 1;
+                       /* des_set_key(cred.session, schedule); */
+                       break;
+#endif
+#endif
+               case 'p':
+                       pflag = 1;
+                       break;
+               case 'r':
+                       iamrecursive = 1;
+                       break;
+                                               /* Server options. */
+               case 'd':
+                       targetshouldbedirectory = 1;
+                       break;
+               case 'f':                       /* "from" */
+                       iamremote = 1;
+                       fflag = 1;
+                       break;
+               case 't':                       /* "to" */
+                       iamremote = 1;
+                       tflag = 1;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+#ifdef KERBEROS
+       if (use_kerberos) {
+#ifdef CRYPT
+               shell = doencrypt ? "ekshell" : "kshell";
+#else
+               shell = "kshell";
+#endif
+               if ((sp = getservbyname(shell, "tcp")) == NULL) {
+                       use_kerberos = 0;
+                       oldw("can't get entry for %s/tcp service", shell);
+                       sp = getservbyname(shell = "shell", "tcp");
+               }
+       } else
+               sp = getservbyname(shell = "shell", "tcp");
+#else
+       sp = getservbyname(shell = "shell", "tcp");
+#endif
+       if (sp == NULL)
+               errx(1, "%s/tcp: unknown service", shell);
+       port = sp->s_port;
+
+       if ((pwd = getpwuid(userid = getuid())) == NULL)
+               errx(1, "unknown user %d", (int)userid);
+
+       rem = STDIN_FILENO;             /* XXX */
+
+       if (fflag) {                    /* Follow "protocol", send data. */
+               (void)response();
+               (void)setuid(userid);
+               source(argc, argv);
+               exit(errs);
+       }
+
+       if (tflag) {                    /* Receive data. */
+               (void)setuid(userid);
+               sink(argc, argv);
+               exit(errs);
+       }
+
+       if (argc < 2)
+               usage();
+       if (argc > 2)
+               targetshouldbedirectory = 1;
+
+       rem = -1;
+       /* Command to be executed on remote system using "rsh". */
+#ifdef KERBEROS
+       (void)snprintf(cmd, sizeof(cmd),
+           "rcp%s%s%s%s", iamrecursive ? " -r" : "",
+#ifdef CRYPT
+           (doencrypt && use_kerberos ? " -x" : ""),
+#else
+           "",
+#endif
+           pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
+#else
+       (void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s",
+           iamrecursive ? " -r" : "", pflag ? " -p" : "",
+           targetshouldbedirectory ? " -d" : "");
+#endif
+
+       (void)signal(SIGPIPE, lostconn);
+
+       if (targ = colon(argv[argc - 1]))       /* Dest is remote host. */
+               toremote(targ, argc, argv);
+       else {
+               tolocal(argc, argv);            /* Dest is local host. */
+               if (targetshouldbedirectory)
+                       verifydir(argv[argc - 1]);
+       }
+       exit(errs);
+}
+
+void
+toremote(targ, argc, argv)
+       char *targ, *argv[];
+       int argc;
+{
+       int i, len, tos;
+       char *bp, *host, *src, *suser, *thost, *tuser;
+
+       *targ++ = 0;
+       if (*targ == 0)
+               targ = ".";
+
+       if (thost = strchr(argv[argc - 1], '@')) {
+               /* user@host */
+               *thost++ = 0;
+               tuser = argv[argc - 1];
+               if (*tuser == '\0')
+                       tuser = NULL;
+               else if (!okname(tuser))
+                       exit(1);
+       } else {
+               thost = argv[argc - 1];
+               tuser = NULL;
+       }
+
+       for (i = 0; i < argc - 1; i++) {
+               src = colon(argv[i]);
+               if (src) {                      /* remote to remote */
+                       *src++ = 0;
+                       if (*src == 0)
+                               src = ".";
+                       host = strchr(argv[i], '@');
+                       len = strlen(_PATH_RSH) + strlen(argv[i]) +
+                           strlen(src) + (tuser ? strlen(tuser) : 0) +
+                           strlen(thost) + strlen(targ) + CMDNEEDS + 20;
+                       if (!(bp = malloc(len)))
+                               err(1, NULL);
+                       if (host) {
+                               *host++ = 0;
+                               suser = argv[i];
+                               if (*suser == '\0')
+                                       suser = pwd->pw_name;
+                               else if (!okname(suser))
+                                       continue;
+                               (void)snprintf(bp, len,
+                                   "%s %s -l %s -n %s %s '%s%s%s:%s'",
+                                   _PATH_RSH, host, suser, cmd, src,
+                                   tuser ? tuser : "", tuser ? "@" : "",
+                                   thost, targ);
+                       } else
+                               (void)snprintf(bp, len,
+                                   "exec %s %s -n %s %s '%s%s%s:%s'",
+                                   _PATH_RSH, argv[i], cmd, src,
+                                   tuser ? tuser : "", tuser ? "@" : "",
+                                   thost, targ);
+                       (void)susystem(bp, userid);
+                       (void)free(bp);
+               } else {                        /* local to remote */
+                       if (rem == -1) {
+                               len = strlen(targ) + CMDNEEDS + 20;
+                               if (!(bp = malloc(len)))
+                                       err(1, NULL);
+                               (void)snprintf(bp, len, "%s -t %s", cmd, targ);
+                               host = thost;
+#ifdef KERBEROS
+                               if (use_kerberos)
+                                       rem = kerberos(&host, bp,
+                                           pwd->pw_name,
+                                           tuser ? tuser : pwd->pw_name);
+                               else
+#endif
+                                       rem = rcmd(&host, port, pwd->pw_name,
+                                           tuser ? tuser : pwd->pw_name,
+                                           bp, 0);
+                               if (rem < 0)
+                                       exit(1);
+                               tos = IPTOS_THROUGHPUT;
+                               if (setsockopt(rem, IPPROTO_IP, IP_TOS,
+                                   &tos, sizeof(int)) < 0)
+                                       warn("TOS (ignored)");
+                               if (response() < 0)
+                                       exit(1);
+                               (void)free(bp);
+                               (void)setuid(userid);
+                       }
+                       source(1, argv+i);
+               }
+       }
+}
+
+void
+tolocal(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int i, len, tos;
+       char *bp, *host, *src, *suser;
+
+       for (i = 0; i < argc - 1; i++) {
+               if (!(src = colon(argv[i]))) {          /* Local to local. */
+                       len = strlen(_PATH_CP) + strlen(argv[i]) +
+                           strlen(argv[argc - 1]) + 20;
+                       if (!(bp = malloc(len)))
+                               err(1, NULL);
+                       (void)snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP,
+                           iamrecursive ? " -r" : "", pflag ? " -p" : "",
+                           argv[i], argv[argc - 1]);
+                       if (susystem(bp, userid))
+                               ++errs;
+                       (void)free(bp);
+                       continue;
+               }
+               *src++ = 0;
+               if (*src == 0)
+                       src = ".";
+               if ((host = strchr(argv[i], '@')) == NULL) {
+                       host = argv[i];
+                       suser = pwd->pw_name;
+               } else {
+                       *host++ = 0;
+                       suser = argv[i];
+                       if (*suser == '\0')
+                               suser = pwd->pw_name;
+                       else if (!okname(suser))
+                               continue;
+               }
+               len = strlen(src) + CMDNEEDS + 20;
+               if ((bp = malloc(len)) == NULL)
+                       err(1, NULL);
+               (void)snprintf(bp, len, "%s -f %s", cmd, src);
+               rem = 
+#ifdef KERBEROS
+                   use_kerberos ? 
+                       kerberos(&host, bp, pwd->pw_name, suser) : 
+#endif
+                       rcmd(&host, port, pwd->pw_name, suser, bp, 0);
+               (void)free(bp);
+               if (rem < 0) {
+                       ++errs;
+                       continue;
+               }
+               (void)seteuid(userid);
+               tos = IPTOS_THROUGHPUT;
+               if (setsockopt(rem, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
+                       warn("TOS (ignored)");
+               sink(1, argv + argc - 1);
+               (void)seteuid(0);
+               (void)close(rem);
+               rem = -1;
+       }
+}
+
+void
+source(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct stat stb;
+       static BUF buffer;
+       BUF *bp;
+       off_t i;
+       int amt, fd, haderr, indx, result;
+       char *last, *name, buf[BUFSIZ];
+
+       for (indx = 0; indx < argc; ++indx) {
+                name = argv[indx];
+               if ((fd = open(name, O_RDONLY, 0)) < 0)
+                       goto syserr;
+               if (fstat(fd, &stb)) {
+syserr:                        run_err("%s: %s", name, strerror(errno));
+                       goto next;
+               }
+               switch (stb.st_mode & S_IFMT) {
+               case S_IFREG:
+                       break;
+               case S_IFDIR:
+                       if (iamrecursive) {
+                               rsource(name, &stb);
+                               goto next;
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       run_err("%s: not a regular file", name);
+                       goto next;
+               }
+               if ((last = strrchr(name, '/')) == NULL)
+                       last = name;
+               else
+                       ++last;
+               if (pflag) {
+                       /*
+                        * Make it compatible with possible future
+                        * versions expecting microseconds.
+                        */
+                       (void)snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
+                           stb.st_mtimespec.tv_sec, stb.st_atimespec.tv_sec);
+                       (void)write(rem, buf, strlen(buf));
+                       if (response() < 0)
+                               goto next;
+               }
+#define        MODEMASK        (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
+               (void)snprintf(buf, sizeof(buf), "C%04o %qd %s\n",
+                   stb.st_mode & MODEMASK, stb.st_size, last);
+               (void)write(rem, buf, strlen(buf));
+               if (response() < 0)
+                       goto next;
+               if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) {
+next:                  (void)close(fd);
+                       continue;
+               }
+
+               /* Keep writing after an error so that we stay sync'd up. */
+               for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
+                       amt = bp->cnt;
+                       if (i + amt > stb.st_size)
+                               amt = stb.st_size - i;
+                       if (!haderr) {
+                               result = read(fd, bp->buf, amt);
+                               if (result != amt)
+                                       haderr = result >= 0 ? EIO : errno;
+                       }
+                       if (haderr)
+                               (void)write(rem, bp->buf, amt);
+                       else {
+                               result = write(rem, bp->buf, amt);
+                               if (result != amt)
+                                       haderr = result >= 0 ? EIO : errno;
+                       }
+               }
+               if (close(fd) && !haderr)
+                       haderr = errno;
+               if (!haderr)
+                       (void)write(rem, "", 1);
+               else
+                       run_err("%s: %s", name, strerror(haderr));
+               (void)response();
+       }
+}
+
+void
+rsource(name, statp)
+       char *name;
+       struct stat *statp;
+{
+       DIR *dirp;
+       struct dirent *dp;
+       char *last, *vect[1], path[MAXPATHLEN];
+
+       if (!(dirp = opendir(name))) {
+               run_err("%s: %s", name, strerror(errno));
+               return;
+       }
+       last = strrchr(name, '/');
+       if (last == 0)
+               last = name;
+       else
+               last++;
+       if (pflag) {
+               (void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n",
+                   statp->st_mtimespec.tv_sec, statp->st_atimespec.tv_sec);
+               (void)write(rem, path, strlen(path));
+               if (response() < 0) {
+                       closedir(dirp);
+                       return;
+               }
+       }
+       (void)snprintf(path, sizeof(path),
+           "D%04o %d %s\n", statp->st_mode & MODEMASK, 0, last);
+       (void)write(rem, path, strlen(path));
+       if (response() < 0) {
+               closedir(dirp);
+               return;
+       }
+       while (dp = readdir(dirp)) {
+               if (dp->d_ino == 0)
+                       continue;
+               if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+                       continue;
+               if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
+                       run_err("%s/%s: name too long", name, dp->d_name);
+                       continue;
+               }
+               (void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name);
+               vect[0] = path;
+               source(1, vect);
+       }
+       (void)closedir(dirp);
+       (void)write(rem, "E\n", 2);
+       (void)response();
+}
+
+void
+sink(argc, argv)
+       int argc;
+       char *argv[];
+{
+       static BUF buffer;
+       struct stat stb;
+       struct timeval tv[2];
+       enum { YES, NO, DISPLAYED } wrerr;
+       BUF *bp;
+       off_t i, j;
+       int amt, count, exists, first, mask, mode, ofd, omode;
+       int setimes, size, targisdir, wrerrno;
+       char ch, *cp, *np, *targ, *why, *vect[1], buf[BUFSIZ];
+
+#define        atime   tv[0]
+#define        mtime   tv[1]
+#define        SCREWUP(str)    { why = str; goto screwup; }
+
+       setimes = targisdir = 0;
+       mask = umask(0);
+       if (!pflag)
+               (void)umask(mask);
+       if (argc != 1) {
+               run_err("ambiguous target");
+               exit(1);
+       }
+       targ = *argv;
+       if (targetshouldbedirectory)
+               verifydir(targ);
+       (void)write(rem, "", 1);
+       if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
+               targisdir = 1;
+       for (first = 1;; first = 0) {
+               cp = buf;
+               if (read(rem, cp, 1) <= 0)
+                       return;
+               if (*cp++ == '\n')
+                       SCREWUP("unexpected <newline>");
+               do {
+                       if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
+                               SCREWUP("lost connection");
+                       *cp++ = ch;
+               } while (cp < &buf[BUFSIZ - 1] && ch != '\n');
+               *cp = 0;
+
+               if (buf[0] == '\01' || buf[0] == '\02') {
+                       if (iamremote == 0)
+                               (void)write(STDERR_FILENO,
+                                   buf + 1, strlen(buf + 1));
+                       if (buf[0] == '\02')
+                               exit(1);
+                       ++errs;
+                       continue;
+               }
+               if (buf[0] == 'E') {
+                       (void)write(rem, "", 1);
+                       return;
+               }
+
+               if (ch == '\n')
+                       *--cp = 0;
+
+#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
+               cp = buf;
+               if (*cp == 'T') {
+                       setimes++;
+                       cp++;
+                       getnum(mtime.tv_sec);
+                       if (*cp++ != ' ')
+                               SCREWUP("mtime.sec not delimited");
+                       getnum(mtime.tv_usec);
+                       if (*cp++ != ' ')
+                               SCREWUP("mtime.usec not delimited");
+                       getnum(atime.tv_sec);
+                       if (*cp++ != ' ')
+                               SCREWUP("atime.sec not delimited");
+                       getnum(atime.tv_usec);
+                       if (*cp++ != '\0')
+                               SCREWUP("atime.usec not delimited");
+                       (void)write(rem, "", 1);
+                       continue;
+               }
+               if (*cp != 'C' && *cp != 'D') {
+                       /*
+                        * Check for the case "rcp remote:foo\* local:bar".
+                        * In this case, the line "No match." can be returned
+                        * by the shell before the rcp command on the remote is
+                        * executed so the ^Aerror_message convention isn't
+                        * followed.
+                        */
+                       if (first) {
+                               run_err("%s", cp);
+                               exit(1);
+                       }
+                       SCREWUP("expected control record");
+               }
+               mode = 0;
+               for (++cp; cp < buf + 5; cp++) {
+                       if (*cp < '0' || *cp > '7')
+                               SCREWUP("bad mode");
+                       mode = (mode << 3) | (*cp - '0');
+               }
+               if (*cp++ != ' ')
+                       SCREWUP("mode not delimited");
+
+               for (size = 0; isdigit(*cp);)
+                       size = size * 10 + (*cp++ - '0');
+               if (*cp++ != ' ')
+                       SCREWUP("size not delimited");
+               if (targisdir) {
+                       static char *namebuf;
+                       static int cursize;
+                       size_t need;
+
+                       need = strlen(targ) + strlen(cp) + 250;
+                       if (need > cursize) {
+                               if (!(namebuf = malloc(need)))
+                                       run_err("%s", strerror(errno));
+                       }
+                       (void)snprintf(namebuf, need, "%s%s%s", targ,
+                           *targ ? "/" : "", cp);
+                       np = namebuf;
+               } else
+                       np = targ;
+               exists = stat(np, &stb) == 0;
+               if (buf[0] == 'D') {
+                       int mod_flag = pflag;
+                       if (exists) {
+                               if (!S_ISDIR(stb.st_mode)) {
+                                       errno = ENOTDIR;
+                                       goto bad;
+                               }
+                               if (pflag)
+                                       (void)chmod(np, mode);
+                       } else {
+                               /* Handle copying from a read-only directory */
+                               mod_flag = 1;
+                               if (mkdir(np, mode | S_IRWXU) < 0)
+                                       goto bad;
+                       }
+                       vect[0] = np;
+                       sink(1, vect);
+                       if (setimes) {
+                               setimes = 0;
+                               if (utimes(np, tv) < 0)
+                                   run_err("%s: set times: %s",
+                                       np, strerror(errno));
+                       }
+                       if (mod_flag)
+                               (void)chmod(np, mode);
+                       continue;
+               }
+               omode = mode;
+               mode |= S_IWRITE;
+               if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
+bad:                   run_err("%s: %s", np, strerror(errno));
+                       continue;
+               }
+               (void)write(rem, "", 1);
+               if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) {
+                       (void)close(ofd);
+                       continue;
+               }
+               cp = bp->buf;
+               wrerr = NO;
+               for (count = i = 0; i < size; i += BUFSIZ) {
+                       amt = BUFSIZ;
+                       if (i + amt > size)
+                               amt = size - i;
+                       count += amt;
+                       do {
+                               j = read(rem, cp, amt);
+                               if (j <= 0) {
+                                       run_err("%s", j ? strerror(errno) :
+                                           "dropped connection");
+                                       exit(1);
+                               }
+                               amt -= j;
+                               cp += j;
+                       } while (amt > 0);
+                       if (count == bp->cnt) {
+                               /* Keep reading so we stay sync'd up. */
+                               if (wrerr == NO) {
+                                       j = write(ofd, bp->buf, count);
+                                       if (j != count) {
+                                               wrerr = YES;
+                                               wrerrno = j >= 0 ? EIO : errno; 
+                                       }
+                               }
+                               count = 0;
+                               cp = bp->buf;
+                       }
+               }
+               if (count != 0 && wrerr == NO &&
+                   (j = write(ofd, bp->buf, count)) != count) {
+                       wrerr = YES;
+                       wrerrno = j >= 0 ? EIO : errno; 
+               }
+               if (ftruncate(ofd, size)) {
+                       run_err("%s: truncate: %s", np, strerror(errno));
+                       wrerr = DISPLAYED;
+               }
+               if (pflag) {
+                       if (exists || omode != mode)
+                               if (fchmod(ofd, omode))
+                                       run_err("%s: set mode: %s",
+                                           np, strerror(errno));
+               } else {
+                       if (!exists && omode != mode)
+                               if (fchmod(ofd, omode & ~mask))
+                                       run_err("%s: set mode: %s",
+                                           np, strerror(errno));
+               }
+               (void)close(ofd);
+               (void)response();
+               if (setimes && wrerr == NO) {
+                       setimes = 0;
+                       if (utimes(np, tv) < 0) {
+                               run_err("%s: set times: %s",
+                                   np, strerror(errno));
+                               wrerr = DISPLAYED;
+                       }
+               }
+               switch(wrerr) {
+               case YES:
+                       run_err("%s: %s", np, strerror(wrerrno));
+                       break;
+               case NO:
+                       (void)write(rem, "", 1);
+                       break;
+               case DISPLAYED:
+                       break;
+               }
+       }
+screwup:
+       run_err("protocol error: %s", why);
+       exit(1);
+}
+
+#ifdef KERBEROS
+int
+kerberos(host, bp, locuser, user)
+       char **host, *bp, *locuser, *user;
+{
+       struct servent *sp;
+
+again:
+       if (use_kerberos) {
+               rem = KSUCCESS;
+               errno = 0;
+               if (dest_realm == NULL)
+                       dest_realm = krb_realmofhost(*host);
+               rem = 
+#ifdef CRYPT
+                   doencrypt ? 
+                       krcmd_mutual(host,
+                           port, user, bp, 0, dest_realm, &cred, schedule) :
+#endif
+                       krcmd(host, port, user, bp, 0, dest_realm);
+
+               if (rem < 0) {
+                       use_kerberos = 0;
+                       if ((sp = getservbyname("shell", "tcp")) == NULL)
+                               errx(1, "unknown service shell/tcp");
+                       if (errno == ECONNREFUSED)
+                           oldw("remote host doesn't support Kerberos");
+                       else if (errno == ENOENT)
+                           oldw("can't provide Kerberos authentication data");
+                       port = sp->s_port;
+                       goto again;
+               }
+       } else {
+#ifdef CRYPT
+               if (doencrypt)
+                       errx(1,
+                          "the -x option requires Kerberos authentication");
+#endif
+               rem = rcmd(host, port, locuser, user, bp, 0);
+       }
+       return (rem);
+}
+#endif /* KERBEROS */
+
+int
+response()
+{
+       char ch, *cp, resp, rbuf[BUFSIZ];
+
+       if (read(rem, &resp, sizeof(resp)) != sizeof(resp))
+               lostconn(0);
+
+       cp = rbuf;
+       switch(resp) {
+       case 0:                         /* ok */
+               return (0);
+       default:
+               *cp++ = resp;
+               /* FALLTHROUGH */
+       case 1:                         /* error, followed by error msg */
+       case 2:                         /* fatal error, "" */
+               do {
+                       if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
+                               lostconn(0);
+                       *cp++ = ch;
+               } while (cp < &rbuf[BUFSIZ] && ch != '\n');
+
+               if (!iamremote)
+                       (void)write(STDERR_FILENO, rbuf, cp - rbuf);
+               ++errs;
+               if (resp == 1)
+                       return (-1);
+               exit(1);
+       }
+       /* NOTREACHED */
+}
+
+void
+usage()
+{
+#ifdef KERBEROS
+#ifdef CRYPT
+       (void)fprintf(stderr, "%s\n\t%s\n",
+           "usage: rcp [-Kpx] [-k realm] f1 f2",
+           "or: rcp [-Kprx] [-k realm] f1 ... fn directory");
+#else
+       (void)fprintf(stderr, "%s\n\t%s\n",
+           "usage: rcp [-Kp] [-k realm] f1 f2",
+           "or: rcp [-Kpr] [-k realm] f1 ... fn directory");
+#endif
+#else
+       (void)fprintf(stderr,
+           "usage: rcp [-p] f1 f2; or: rcp [-pr] f1 ... fn directory\n");
+#endif
+       exit(1);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef KERBEROS
+void
+#if __STDC__
+oldw(const char *fmt, ...)
+#else
+oldw(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)fprintf(stderr, "rcp: ");
+       (void)vfprintf(stderr, fmt, ap);
+       (void)fprintf(stderr, ", using standard rcp\n");
+       va_end(ap);
+}
+#endif
+
+void
+#if __STDC__
+run_err(const char *fmt, ...)
+#else
+run_err(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       static FILE *fp;
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+
+       ++errs;
+       if (fp == NULL && !(fp = fdopen(rem, "w")))
+               return;
+       (void)fprintf(fp, "%c", 0x01);
+       (void)fprintf(fp, "rcp: ");
+       (void)vfprintf(fp, fmt, ap);
+       (void)fprintf(fp, "\n");
+       (void)fflush(fp);
+
+       if (!iamremote)
+               vwarnx(fmt, ap);
+
+       va_end(ap);
+}
diff --git a/rcp.tproj/util.c b/rcp.tproj/util.c
new file mode 100644 (file)
index 0000000..7ee6866
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+char *
+colon(cp)
+       char *cp;
+{
+       if (*cp == ':')         /* Leading colon is part of file name. */
+               return (0);
+
+       for (; *cp; ++cp) {
+               if (*cp == ':')
+                       return (cp);
+               if (*cp == '/')
+                       return (0);
+       }
+       return (0);
+}
+
+void
+verifydir(cp)
+       char *cp;
+{
+       struct stat stb;
+
+       if (!stat(cp, &stb)) {
+               if (S_ISDIR(stb.st_mode))
+                       return;
+               errno = ENOTDIR;
+       }
+       run_err("%s: %s", cp, strerror(errno));
+       exit(1);
+}
+
+int
+okname(cp0)
+       char *cp0;
+{
+       int c;
+       char *cp;
+
+       cp = cp0;
+       do {
+               c = *cp;
+               if (c & 0200)
+                       goto bad;
+               if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
+                       goto bad;
+       } while (*++cp);
+       return (1);
+
+bad:   warnx("%s: invalid user name", cp0);
+       return (0);
+}
+
+int
+susystem(s, userid)
+       int userid;
+       char *s;
+{
+       sig_t istat, qstat;
+       int status, w;
+       pid_t pid;
+
+       pid = vfork();
+       switch (pid) {
+       case -1:
+               return (127);
+       
+       case 0:
+               (void)setuid(userid);
+               execl(_PATH_BSHELL, "sh", "-c", s, NULL);
+               _exit(127);
+       }
+       istat = signal(SIGINT, SIG_IGN);
+       qstat = signal(SIGQUIT, SIG_IGN);
+       if (waitpid(pid, &status, 0) < 0)
+               status = -1;
+       (void)signal(SIGINT, istat);
+       (void)signal(SIGQUIT, qstat);
+       return (status);
+}
+
+BUF *
+allocbuf(bp, fd, blksize)
+       BUF *bp;
+       int fd, blksize;
+{
+       struct stat stb;
+       size_t size;
+
+       if (fstat(fd, &stb) < 0) {
+               run_err("fstat: %s", strerror(errno));
+               return (0);
+       }
+       size = roundup(stb.st_blksize, blksize);
+       if (size == 0)
+               size = blksize;
+       if (bp->cnt >= size)
+               return (bp);
+       if ((bp->buf = realloc(bp->buf, size)) == NULL) {
+               bp->cnt = 0;
+               run_err("%s", strerror(errno));
+               return (0);
+       }
+       bp->cnt = size;
+       return (bp);
+}
+
+void
+lostconn(signo)
+       int signo;
+{
+       if (!iamremote)
+               warnx("lost connection");
+       exit(1);
+}
diff --git a/revnetgroup.tproj/Makefile b/revnetgroup.tproj/Makefile
new file mode 100644 (file)
index 0000000..a494108
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = revnetgroup
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = hash.h
+
+CFILES = hash.c parse_netgroup.c revnetgroup.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble revnetgroup.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/revnetgroup.tproj/Makefile.postamble b/revnetgroup.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/revnetgroup.tproj/Makefile.preamble b/revnetgroup.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/revnetgroup.tproj/PB.project b/revnetgroup.tproj/PB.project
new file mode 100644 (file)
index 0000000..3a8d039
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (hash.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (hash.c, parse_netgroup.c, revnetgroup.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, revnetgroup.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = revnetgroup; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/revnetgroup.tproj/hash.c b/revnetgroup.tproj/hash.c
new file mode 100644 (file)
index 0000000..9aee4bd
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $ */
+/*
+ * Copyright (c) 1995
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $FreeBSD: hash.c,v 1.4 1997/02/22 14:22:01 peter Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "hash.h"
+
+#ifndef lint
+static const char rcsid[] = "$OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $";
+#endif
+
+/*
+ * This hash function is stolen directly from the
+ * Berkeley DB package. It already exists inside libc, but
+ * it's declared static which prevents us from calling it
+ * from here.
+ */
+/*
+ * OZ's original sdbm hash
+ */
+u_int32_t
+hash(keyarg, len)
+       const void *keyarg;
+       register size_t len;
+{
+       register const u_char *key;
+       register size_t loop;
+       register u_int32_t h;
+
+#define HASHC   h = *key++ + 65599 * h
+
+       h = 0;
+       key = keyarg;
+       if (len > 0) {
+               loop = (len + 8 - 1) >> 3;
+
+               switch (len & (8 - 1)) {
+               case 0:
+                       do {
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 7:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 6:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 5:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 4:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 3:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 2:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 1:
+                               HASHC;
+                       } while (--loop);
+               }
+       }
+       return (h);
+}
+
+/*
+ * Generate a hash value for a given key (character string).
+ * We mask off all but the lower 8 bits since our table array
+ * can only hold 256 elements.
+ */
+u_int32_t hashkey(key)
+       char *key;
+{
+
+       if (key == NULL)
+               return (-1);
+       return(hash((void *)key, strlen(key)) & HASH_MASK);
+}
+
+/* Find an entry in the hash table (may be hanging off a linked list). */
+char *lookup(table, key)
+       struct group_entry *table[];
+       char *key;
+{
+       struct group_entry *cur;
+
+       cur = table[hashkey(key)];
+
+       while (cur) {
+               if (!strcmp(cur->key, key))
+                       return(cur->data);
+               cur = cur->next;
+       }
+
+       return(NULL);
+}
+
+/*
+ * Store an entry in the main netgroup hash table. Here's how this
+ * works: the table can only be so big when we initialize it (TABLESIZE)
+ * but the number of netgroups in the /etc/netgroup file could easily be
+ * much larger than the table. Since our hash values are adjusted to
+ * never be greater than TABLESIZE too, this means it won't be long before
+ * we find ourselves with two keys that hash to the same value.
+ *
+ * One way to deal with this is to malloc(2) a second table and start
+ * doing indirection, but this is a pain in the butt and it's not worth
+ * going to all that trouble for a dinky little program like this. Instead,
+ * we turn each table entry into a linked list and simply link keys
+ * with the same hash value together at the same index location within
+ * the table.
+ *
+ * That's a lot of comment for such a small piece of code, isn't it.
+ */
+void store (table, key, data)
+       struct group_entry *table[];
+       char *key, *data;
+{
+       struct group_entry *new;
+       u_int32_t i;
+
+       i = hashkey(key);
+
+       new = (struct group_entry *)malloc(sizeof(struct group_entry));
+       new->key = strdup(key);
+       new->data = strdup(data);
+       new->next = table[i];
+       table[i] = new;
+
+       return;
+}
+
+/*
+ * Store a group member entry and/or update its grouplist. This is
+ * a bit more complicated than the previous function since we have to
+ * maintain not only the hash table of group members, each group member
+ * structure also has a linked list of groups hung off it. If handed
+ * a member name that we haven't encountered before, we have to do
+ * two things: add that member to the table (possibly hanging them
+ * off the end of a linked list, as above), and add a group name to
+ * the member's grouplist list. If we're handed a name that already has
+ * an entry in the table, then we just have to do one thing, which is
+ * to update its grouplist.
+ */
+void mstore (table, key, data, domain)
+       struct member_entry *table[];
+       char *key, *data, *domain;
+{
+       struct member_entry *cur, *new;
+       struct grouplist *tmp,*p;
+       u_int32_t i;
+
+       i = hashkey(key);
+       cur = table[i];
+
+       tmp = (struct grouplist *)malloc(sizeof(struct grouplist));
+       tmp->groupname = strdup(data);
+       tmp->next = NULL;
+
+       /* Check if all we have to do is insert a new groupname. */
+       while (cur) {
+               if (!strcmp(cur->key, key) && !strcmp(cur->domain,domain)) {
+                       p = cur->groups;
+                       while(p) {
+                               if (!strcmp(p->groupname,data))
+                                       return;
+                               p = p->next;
+                       }
+                       tmp->next = cur->groups;
+                       cur->groups = tmp;
+                       return;
+               }
+               cur = cur->next;
+       }
+
+       /* Didn't find a match -- add the whole mess to the table. */
+       new = (struct member_entry *)malloc(sizeof(struct member_entry));
+       new->key = strdup(key);
+       new->domain = strdup(domain);
+       new->groups = tmp;
+       new->next = table[i];
+       table[i] = new;
+
+       return;
+}
diff --git a/revnetgroup.tproj/hash.h b/revnetgroup.tproj/hash.h
new file mode 100644 (file)
index 0000000..822c9e0
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $OpenBSD: hash.h,v 1.1 1997/04/15 22:06:12 maja Exp $ */
+/*
+ * Copyright (c) 1995
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $FreeBSD: hash.h,v 1.5 1997/02/22 14:22:02 peter Exp $
+ */
+
+/* Groupname entry hung off a member_entry node. */
+struct grouplist {
+       char *groupname;
+       struct grouplist *next;
+};
+
+/* Entry in the cooked member list hash table. */
+struct member_entry {
+       char *key;
+       char *domain;
+       struct grouplist *groups;
+       struct member_entry *next;
+};
+
+/* Entry in the raw netgroup table. */
+struct group_entry {
+       char *key;
+       char *data;
+       struct group_entry *next;
+};
+
+/* Table size (chosen arbitrarily). Not too big, not too small. */
+#define TABLESIZE 256
+#define HASH_MASK 0x000000FF
+
+#define LINSIZ 1024 * 10
+
+extern void store __P(( struct group_entry ** , char *, char * ));
+extern void mstore __P(( struct member_entry ** , char *, char *, char * ));
+extern char *lookup __P(( struct group_entry **, char * ));
+extern void __endnetgrent __P(( void ));
+extern void __setnetgrent __P(( char * ));
+extern int __getnetgrent __P(( char **, char **, char ** ));
diff --git a/revnetgroup.tproj/parse_netgroup.c b/revnetgroup.tproj/parse_netgroup.c
new file mode 100644 (file)
index 0000000..0d1e07a
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $OpenBSD: parse_netgroup.c,v 1.2 1997/08/18 03:11:35 millert Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $FreeBSD: parse_netgroup.c,v 1.5 1997/02/22 14:22:02 peter Exp $
+ */
+
+/*
+ * This is a specially hacked-up version of getnetgrent.c used to parse
+ * data from the stored hash table of netgroup info rather than from a
+ * file. It's used mainly for the parse_netgroup() function. All the YP
+ * stuff and file support has been stripped out since it isn't needed.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "hash.h"
+
+#ifndef lint
+static const char rcsid[] = "$OpenBSD: parse_netgroup.c,v 1.2 1997/08/18 03:11:35 millert Exp $";
+#endif
+
+/*
+ * Static Variables and functions used by setnetgrent(), getnetgrent() and
+ * __endnetgrent().
+ * There are two linked lists:
+ * - linelist is just used by setnetgrent() to parse the net group file via.
+ *   parse_netgrp()
+ * - netgrp is the list of entries for the current netgroup
+ */
+struct linelist {
+       struct linelist *l_next;        /* Chain ptr. */
+       int             l_parsed;       /* Flag for cycles */
+       char            *l_groupname;   /* Name of netgroup */
+       char            *l_line;        /* Netgroup entrie(s) to be parsed */
+};
+
+struct netgrp {
+       struct netgrp   *ng_next;       /* Chain ptr */
+       char            *ng_str[3];     /* Field pointers, see below */
+};
+#define NG_HOST                0       /* Host name */
+#define NG_USER                1       /* User name */
+#define NG_DOM         2       /* and Domain name */
+
+static struct linelist *linehead = (struct linelist *)0;
+static struct netgrp   *nextgrp = (struct netgrp *)0;
+static struct {
+       struct netgrp   *gr;
+       char            *grname;
+} grouphead = {
+       (struct netgrp *)0,
+       (char *)0,
+};
+static int parse_netgrp();
+static struct linelist *read_for_group();
+void __setnetgrent(), __endnetgrent();
+int __getnetgrent();
+extern struct group_entry *gtable[];
+
+/*
+ * setnetgrent()
+ * Parse the netgroup file looking for the netgroup and build the list
+ * of netgrp structures. Let parse_netgrp() and read_for_group() do
+ * most of the work.
+ */
+void
+__setnetgrent(group)
+       char *group;
+{
+       /* Sanity check */
+
+       if (group == NULL || !strlen(group))
+               return;
+
+       if (grouphead.gr == (struct netgrp *)0 ||
+               strcmp(group, grouphead.grname)) {
+               __endnetgrent();
+               if (parse_netgrp(group))
+                       __endnetgrent();
+               else {
+                       grouphead.grname = (char *)
+                               malloc(strlen(group) + 1);
+                       strcpy(grouphead.grname, group);
+               }
+       }
+       nextgrp = grouphead.gr;
+}
+
+/*
+ * Get the next netgroup off the list.
+ */
+int
+__getnetgrent(hostp, userp, domp)
+       char **hostp, **userp, **domp;
+{
+       if (nextgrp) {
+               *hostp = nextgrp->ng_str[NG_HOST];
+               *userp = nextgrp->ng_str[NG_USER];
+               *domp = nextgrp->ng_str[NG_DOM];
+               nextgrp = nextgrp->ng_next;
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * __endnetgrent() - cleanup
+ */
+void
+__endnetgrent()
+{
+       register struct linelist *lp, *olp;
+       register struct netgrp *gp, *ogp;
+
+       lp = linehead;
+       while (lp) {
+               olp = lp;
+               lp = lp->l_next;
+               free(olp->l_groupname);
+               free(olp->l_line);
+               free((char *)olp);
+       }
+       linehead = (struct linelist *)0;
+       if (grouphead.grname) {
+               free(grouphead.grname);
+               grouphead.grname = (char *)0;
+       }
+       gp = grouphead.gr;
+       while (gp) {
+               ogp = gp;
+               gp = gp->ng_next;
+               if (ogp->ng_str[NG_HOST])
+                       free(ogp->ng_str[NG_HOST]);
+               if (ogp->ng_str[NG_USER])
+                       free(ogp->ng_str[NG_USER]);
+               if (ogp->ng_str[NG_DOM])
+                       free(ogp->ng_str[NG_DOM]);
+               free((char *)ogp);
+       }
+       grouphead.gr = (struct netgrp *)0;
+}
+
+/*
+ * Parse the netgroup file setting up the linked lists.
+ */
+static int
+parse_netgrp(group)
+       char *group;
+{
+       register char *spos, *epos;
+       register int len, strpos;
+#ifdef DEBUG
+       register int fields;
+#endif
+       char *pos, *gpos;
+       struct netgrp *grp;
+       struct linelist *lp = linehead;
+
+       /*
+        * First, see if the line has already been read in.
+        */
+       while (lp) {
+               if (!strcmp(group, lp->l_groupname))
+                       break;
+               lp = lp->l_next;
+       }
+       if (lp == (struct linelist *)0 &&
+           (lp = read_for_group(group)) == (struct linelist *)0)
+               return (1);
+       if (lp->l_parsed) {
+#ifdef DEBUG
+               /*
+                * This error message is largely superflous since the
+                * code handles the error condition sucessfully, and
+                * spewing it out from inside libc can actually hose
+                * certain programs.
+                */
+               fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
+#endif
+               return (1);
+       } else
+               lp->l_parsed = 1;
+       pos = lp->l_line;
+       /* Watch for null pointer dereferences, dammit! */
+       while (pos != NULL && *pos != '\0') {
+               if (*pos == '(') {
+                       grp = (struct netgrp *)malloc(sizeof (struct netgrp));
+                       bzero((char *)grp, sizeof (struct netgrp));
+                       grp->ng_next = grouphead.gr;
+                       grouphead.gr = grp;
+                       pos++;
+                       gpos = strsep(&pos, ")");
+#ifdef DEBUG
+                       fields = 0;
+#endif
+                       for (strpos = 0; strpos < 3; strpos++) {
+                               if ((spos = strsep(&gpos, ","))) {
+#ifdef DEBUG
+                                       fields++;
+#endif
+                                       while (*spos == ' ' || *spos == '\t')
+                                               spos++;
+                                       if ((epos = strpbrk(spos, " \t"))) {
+                                               *epos = '\0';
+                                               len = epos - spos;
+                                       } else
+                                               len = strlen(spos);
+                                       if (len > 0) {
+                                               grp->ng_str[strpos] =  (char *)
+                                                       malloc(len + 1);
+                                               bcopy(spos, grp->ng_str[strpos],
+                                                       len + 1);
+                                       }
+                               } else {
+                                       /*
+                                        * All other systems I've tested
+                                        * return NULL for empty netgroup
+                                        * fields. It's up to user programs
+                                        * to handle the NULLs appropriately.
+                                        */
+                                       grp->ng_str[strpos] = NULL;
+                               }
+                       }
+#ifdef DEBUG
+                       /*
+                        * Note: on other platforms, malformed netgroup
+                        * entries are not normally flagged. While we
+                        * can catch bad entries and report them, we should
+                        * stay silent by default for compatibility's sake.
+                        */
+                       if (fields < 3)
+                                       fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n",
+                                               grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST],
+                                               grp->ng_str[NG_USER] == NULL ? "" : ",",
+                                               grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER],
+                                               grp->ng_str[NG_DOM] == NULL ? "" : ",",
+                                               grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM],
+                                               lp->l_groupname);
+#endif
+               } else {
+                       spos = strsep(&pos, ", \t");
+                       if (parse_netgrp(spos))
+                               continue;
+               }
+               /* Watch for null pointer dereferences, dammit! */
+               if (pos != NULL)
+                       while (*pos == ' ' || *pos == ',' || *pos == '\t')
+                               pos++;
+       }
+       return (0);
+}
+
+/*
+ * Read the netgroup file and save lines until the line for the netgroup
+ * is found. Return 1 if eof is encountered.
+ */
+static struct linelist *
+read_for_group(group)
+       char *group;
+{
+       register char *pos, *spos, *linep = NULL, *olinep = NULL;
+       register int len, olen;
+       int cont;
+       struct linelist *lp;
+       char line[LINSIZ + 1];
+       char *data = NULL;
+
+       data = lookup (gtable, group);
+       sprintf(line, "%s %s", group, data);
+       pos = (char *)&line;
+#ifdef CANT_HAPPEN
+       if (*pos == '#')
+               continue;
+#endif
+       while (*pos == ' ' || *pos == '\t')
+               pos++;
+       spos = pos;
+       while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
+               *pos != '\0')
+               pos++;
+       len = pos - spos;
+       while (*pos == ' ' || *pos == '\t')
+               pos++;
+       if (*pos != '\n' && *pos != '\0') {
+               lp = (struct linelist *)malloc(sizeof (*lp));
+               lp->l_parsed = 0;
+               lp->l_groupname = (char *)malloc(len + 1);
+               bcopy(spos, lp->l_groupname, len);
+               *(lp->l_groupname + len) = '\0';
+               len = strlen(pos);
+               olen = 0;
+                       /*
+                        * Loop around handling line continuations.
+                        */
+                       do {
+                               if (*(pos + len - 1) == '\n')
+                                       len--;
+                               if (*(pos + len - 1) == '\\') {
+                                       len--;
+                                       cont = 1;
+                               } else
+                                       cont = 0;
+                               if (len > 0) {
+                                       linep = (char *)malloc(olen + len + 1);
+                                       if (olen > 0) {
+                                               bcopy(olinep, linep, olen);
+                                               free(olinep);
+                                       }
+                                       bcopy(pos, linep + olen, len);
+                                       olen += len;
+                                       *(linep + olen) = '\0';
+                                       olinep = linep;
+                               }
+#ifdef CANT_HAPPEN
+                               if (cont) {
+                                       if (fgets(line, LINSIZ, netf)) {
+                                               pos = line;
+                                               len = strlen(pos);
+                                       } else
+                                               cont = 0;
+                               }
+#endif
+                       } while (cont);
+               lp->l_line = linep;
+               lp->l_next = linehead;
+               linehead = lp;
+#ifdef CANT_HAPPEN
+               /*
+                * If this is the one we wanted, we are done.
+                */
+               if (!strcmp(lp->l_groupname, group))
+#endif
+                       return (lp);
+       }
+       return ((struct linelist *)0);
+}
diff --git a/revnetgroup.tproj/revnetgroup.8 b/revnetgroup.tproj/revnetgroup.8
new file mode 100644 (file)
index 0000000..aea4095
--- /dev/null
@@ -0,0 +1,138 @@
+.\"    $OpenBSD: revnetgroup.8,v 1.1 1997/04/15 22:06:14 maja Exp $
+.\" Copyright (c) 1995
+.\"    Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Bill Paul.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    $FreeBSD: revnetgroup.8,v 1.4 1997/02/22 14:22:03 peter Exp $
+.\"
+.Dd October 24, 1995
+.Dt REVNETGROUP 8
+.Os
+.Sh NAME
+.Nm revnetgroup
+.Nd "generate reverse netgroup data"
+.Sh SYNOPSIS
+.Nm revnetgroup
+.Fl u
+.Fl h
+.Op Fl f Ar netgroup_file
+.Sh DESCRIPTION
+.Nm revnetgroup
+processes the contents of a file in
+.Xr netgroup 5
+format into what is called
+.Pa reverse netgroup
+form. That is, where the original file shows
+netgroup memberships in terms of which members reside in a particular
+group, the reverse netgroup format specifies what groups are associated
+with a particular member. This information is used to generate the
+.Nm netgroup.byuser
+and
+.Nm netgroup.byhosts
+YP maps. These reverse netgroup maps are used to help speed up
+netgroup lookups, particularly for the
+.Fn innetgr
+library function.
+.Pp
+For example, the standard
+.Nm /etc/netgroup
+file may list a netgroup and a list of its members. Here, the
+netgroup is considered the
+.Pa key
+and the member names are the
+.Pa data .
+By contrast, the reverse
+.Nm netgroup.byusers
+database lists each unique
+member as the key and the netgroups to which the members belong become
+the data. Seperate databases are created to hold information pertaining
+to users and hosts; this allows netgroup username lookups
+and netgroup hostname lookups to be performed using independent keyspaces.
+.Pp
+By constructing these reverse netgroup databases (and the corresponding
+YP maps) in advance, the
+.Xr getnetgrent 3
+library functions are spared from having to work out the dependencies
+themselves on the fly. This is important on networks with large numbers
+of users and hosts, since it can take a considerable amount of time
+to process very large netgroup databases.
+.Pp
+The
+.Nm revnetgroup
+command prints its results on the standard output. It is usually called
+only by
+.Nm /var/yp/\<domain\>/Makefile
+when rebuilding the YP netgroup maps.
+.Pp
+.Sh OPTIONS
+The
+.Nm revnetgroup
+command supports the following options:
+.Bl -tag -width flag
+.It Fl u
+Generate netgroup.byuser output; only username information in the
+original netgroup file is processed.
+.It Fl h
+Generate netgroup.byhost output; only hostname information in the
+original netgroup file is processed. (Note at least one of the
+.Fl u
+or
+.Fl h
+flags must be specified.)
+.It Op Fl f Ar netgroup_file
+The
+.Nm revnetgroup
+command uses
+.Nm /etc/netgroup
+as its default input file. The
+.Fl f
+flag allows the user to specify an alternate input file. Specifying ``-''
+as the input file causes
+.Nm revnetgroup
+to read from the standard input.
+.El
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /var/yp/\<domain\>Makefile
+The Makefile that calls
+.Nm makedbm
+and
+.Nm revnetgroup
+to build the YP databases.
+.It Pa /etc/netgroup
+The default netgroup database file. This file is most often found
+only on the YP master server.
+.El
+.Sh SEE ALSO
+.Xr getnetgrent 3 ,
+.Xr yp 8 ,
+.Xr netgroup 5 ,
+.Xr makedbm 8
+.Sh AUTHOR
+Bill Paul <wpaul@ctr.columbia.edu>
diff --git a/revnetgroup.tproj/revnetgroup.c b/revnetgroup.tproj/revnetgroup.c
new file mode 100644 (file)
index 0000000..a45db99
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $OpenBSD: revnetgroup.c,v 1.1 1997/04/15 22:06:15 maja Exp $ */
+/*
+ * Copyright (c) 1995
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * reverse netgroup map generator program
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ *
+ *     $FreeBSD: revnetgroup.c,v 1.7 1997/03/28 15:48:15 imp Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include "hash.h"
+
+#ifndef lint
+static const char rcsid[] = "$OpenBSD: revnetgroup.c,v 1.1 1997/04/15 22:06:15 maja Exp $";
+#endif
+
+/* Default location of netgroup file. */
+char *netgroup = "/etc/netgroup";
+
+/* Stored hash table version of 'forward' netgroup database. */
+struct group_entry *gtable[TABLESIZE];
+
+/*
+ * Stored hash table of 'reverse' netgroup member database
+ * which we will construct.
+ */
+struct member_entry *mtable[TABLESIZE];
+
+void usage(prog)
+char *prog;
+{
+       fprintf (stderr,"usage: %s -u|-h [-f netgroup file]\n",prog);
+       exit(1);
+}
+
+extern char *optarg;
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       FILE *fp;
+       char readbuf[LINSIZ];
+       struct group_entry *gcur;
+       struct member_entry *mcur;
+       char *host, *user, *domain;
+       int ch;
+       char *key = NULL, *data = NULL;
+       int hosts = -1, i;
+
+       if (argc < 2)
+               usage(argv[0]);
+
+       while ((ch = getopt(argc, argv, "uhf:")) != -1) {
+               switch(ch) {
+               case 'u':
+                       if (hosts != -1) {
+                               warnx("please use only one of -u or -h");
+                               usage(argv[0]);
+                       }
+                       hosts = 0;
+                       break;
+               case 'h':
+                       if (hosts != -1) {
+                               warnx("please use only one of -u or -h");
+                               usage(argv[0]);
+                       }
+                       hosts = 1;
+                       break;
+               case 'f':
+                       netgroup = optarg;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       if (hosts == -1)
+               usage(argv[0]);
+
+       if (strcmp(netgroup, "-")) {
+               if ((fp = fopen(netgroup, "r")) == NULL) {
+                       err(1,netgroup);
+               }
+       } else {
+               fp = stdin;
+       }
+
+       /* Stuff all the netgroup names and members into a hash table. */
+       while (fgets(readbuf, LINSIZ, fp)) {
+               if (readbuf[0] == '#')
+                       continue;
+               /* handle backslash line continuations */
+               while(readbuf[strlen(readbuf) - 2] == '\\') {
+                       fgets((char *)&readbuf[strlen(readbuf) - 2],
+                                       sizeof(readbuf) - strlen(readbuf), fp);
+               }
+               data = NULL;
+               if ((data = (char *)(strpbrk(readbuf, " \t") + 1)) < (char *)2)
+                       continue;
+               key = (char *)&readbuf;
+               *(data - 1) = '\0';
+               store(gtable, key, data);
+       }
+
+       fclose(fp);
+
+       /*
+        * Find all members of each netgroup and keep track of which
+        * group they belong to.
+        */
+       for (i = 0; i < TABLESIZE; i++) {
+               gcur = gtable[i];
+               while(gcur) {
+                       __setnetgrent(gcur->key);
+                       while(__getnetgrent(&host, &user, &domain) != NULL) {
+                               if (hosts) {
+                                       if (!(host && !strcmp(host,"-"))) {
+                                               mstore(mtable,
+                                                      host ? host : "*",
+                                                      gcur->key,
+                                                      domain ? domain : "*");
+                                       }
+                               } else {
+                                       if (!(user && !strcmp(user,"-"))) {
+                                               mstore(mtable,
+                                                      user ? user : "*",
+                                                      gcur->key,
+                                                      domain ? domain : "*");
+                                       }
+                               }
+                       }
+                       gcur = gcur->next;
+               }
+       }
+
+       /* Release resources used by the netgroup parser code. */
+       __endnetgrent();
+
+       /* Spew out the results. */
+       for (i = 0; i < TABLESIZE; i++) {
+               mcur = mtable[i];
+               while(mcur) {
+                       struct grouplist *tmp;
+                       printf ("%s.%s\t", mcur->key, mcur->domain);
+                       tmp = mcur->groups;
+                       while(tmp) {
+                               printf ("%s", tmp->groupname);
+                               tmp = tmp->next;
+                               if (tmp)
+                                       printf(",");
+                       }
+                       mcur = mcur->next;
+                       printf ("\n");
+               }
+       }
+
+       /* Let the OS free all our resources. */
+       exit(0);
+}
diff --git a/rexecd.tproj/Makefile b/rexecd.tproj/Makefile
new file mode 100644 (file)
index 0000000..2b445ca
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rexecd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = rexecd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rexecd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rexecd.tproj/Makefile.postamble b/rexecd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7ede358
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
diff --git a/rexecd.tproj/Makefile.preamble b/rexecd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dcbd1c8
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
diff --git a/rexecd.tproj/PB.project b/rexecd.tproj/PB.project
new file mode 100644 (file)
index 0000000..aa703bb
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (rexecd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rexecd.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rexecd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rexecd.tproj/rexecd.8 b/rexecd.tproj/rexecd.8
new file mode 100644 (file)
index 0000000..3035900
--- /dev/null
@@ -0,0 +1,149 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)rexecd.8   8.3 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt REXECD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm rexecd
+.Nd remote execution server
+.Sh SYNOPSIS
+.Nm rexecd
+.Sh DESCRIPTION
+.Nm Rexecd
+is the server for the 
+.Xr rexec 3
+routine.  The server provides remote execution facilities
+with authentication based on user names and
+passwords.
+.Pp
+.Nm Rexecd
+listens for service requests at the port indicated in
+the ``exec'' service specification; see
+.Xr services 5 .
+When a service request is received the following protocol
+is initiated:
+.Bl -enum
+.It
+The server reads characters from the socket up
+to a NUL
+.Pq Ql \e0
+byte.  The resultant string is
+interpreted as an
+.Tn ASCII
+number, base 10.
+.It 
+If the number received in step 1 is non-zero,
+it is interpreted as the port number of a secondary
+stream to be used for the 
+.Em stderr .
+A second connection is then created to the specified
+port on the client's machine.
+.It
+A NUL terminated user name of at most 16 characters
+is retrieved on the initial socket.
+.It
+A NUL terminated, unencrypted password of at most
+16 characters is retrieved on the initial socket.  
+.It
+A NUL terminated command to be passed to a
+shell is retrieved on the initial socket.  The length of
+the command is limited by the upper bound on the size of
+the system's argument list.  
+.It
+.Nm Rexecd
+then validates the user as is done at login time
+and, if the authentication was successful, changes
+to the user's home directory, and establishes the user
+and group protections of the user.
+If any of these steps fail the connection is
+aborted with a diagnostic message returned.
+.It
+A NUL byte is returned on the initial socket
+and the command line is passed to the normal login
+shell of the user.  The
+shell inherits the network connections established
+by
+.Nm rexecd .
+.El
+.Sh DIAGNOSTICS
+Except for the last one listed below,
+all diagnostic messages are returned on the initial socket,
+after which any network connections are closed.
+An error is indicated by a leading byte with a value of
+1 (0 is returned in step 7 above upon successful completion
+of all the steps prior to the command execution).
+.Pp
+.Bl -tag -width Ds
+.It Sy username too long
+The name is
+longer than 16 characters.
+.It Sy password too long
+The password is longer than 16 characters.
+.It Sy command too long
+The command line passed exceeds the size of the argument
+list (as configured into the system).
+.It Sy Login incorrect.
+No password file entry for the user name existed.
+.It Sy Password incorrect.
+The wrong password was supplied.
+.ne 1i
+.It Sy \&No remote directory.
+The 
+.Xr chdir
+command to the home directory failed.
+.It Sy Try again.
+A
+.Xr fork
+by the server failed.
+.It Sy <shellname>: ...
+The user's login shell could not be started.
+This message is returned
+on the connection associated with the
+.Em stderr ,
+and is not preceded by a flag byte.
+.El
+.Sh SEE ALSO
+.Xr rexec 3
+.Sh BUGS
+Indicating ``Login incorrect'' as opposed to ``Password incorrect''
+is a security breach which allows people to probe a system for users
+with null passwords.
+.Pp
+A facility to allow all data and password exchanges to be encrypted should be
+present.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/rexecd.tproj/rexecd.c b/rexecd.tproj/rexecd.c
new file mode 100644 (file)
index 0000000..ec9e009
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rexecd.c   8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*VARARGS1*/
+int error();
+
+/*
+ * remote execute server:
+ *     username\0
+ *     password\0
+ *     command\0
+ *     data
+ */
+/*ARGSUSED*/
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       struct sockaddr_in from;
+       int fromlen;
+
+       fromlen = sizeof (from);
+       if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+               (void)fprintf(stderr,
+                   "rexecd: getpeername: %s\n", strerror(errno));
+               exit(1);
+       }
+       doit(0, &from);
+}
+
+char   username[20] = "USER=";
+char   homedir[64] = "HOME=";
+char   shell[64] = "SHELL=";
+char   path[sizeof(_PATH_DEFPATH) + sizeof("PATH=")] = "PATH=";
+char   *envinit[] =
+           {homedir, shell, path, username, 0};
+#ifdef __APPLE__
+extern
+#endif
+char   **environ;
+
+struct sockaddr_in asin = { AF_INET };
+
+doit(f, fromp)
+       int f;
+       struct sockaddr_in *fromp;
+{
+       char cmdbuf[NCARGS+1], *cp, *namep;
+       char user[16], pass[16];
+       struct passwd *pwd;
+       int s;
+       u_short port;
+       int pv[2], pid, ready, readfrom, cc;
+       char buf[BUFSIZ], sig;
+       int one = 1;
+
+       (void) signal(SIGINT, SIG_DFL);
+       (void) signal(SIGQUIT, SIG_DFL);
+       (void) signal(SIGTERM, SIG_DFL);
+#ifdef DEBUG
+       { int t = open(_PATH_TTY, 2);
+         if (t >= 0) {
+               ioctl(t, TIOCNOTTY, (char *)0);
+               (void) close(t);
+         }
+       }
+#endif
+       dup2(f, 0);
+       dup2(f, 1);
+       dup2(f, 2);
+       (void) alarm(60);
+       port = 0;
+       for (;;) {
+               char c;
+               if (read(f, &c, 1) != 1)
+                       exit(1);
+               if (c == 0)
+                       break;
+               port = port * 10 + c - '0';
+       }
+       (void) alarm(0);
+       if (port != 0) {
+               s = socket(AF_INET, SOCK_STREAM, 0);
+               if (s < 0)
+                       exit(1);
+               if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0)
+                       exit(1);
+               (void) alarm(60);
+               fromp->sin_port = htons(port);
+               if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0)
+                       exit(1);
+               (void) alarm(0);
+       }
+       getstr(user, sizeof(user), "username");
+       getstr(pass, sizeof(pass), "password");
+       getstr(cmdbuf, sizeof(cmdbuf), "command");
+       setpwent();
+       pwd = getpwnam(user);
+       if (pwd == NULL) {
+               error("Login incorrect.\n");
+               exit(1);
+       }
+       endpwent();
+       if (*pwd->pw_passwd != '\0') {
+               namep = crypt(pass, pwd->pw_passwd);
+               if (strcmp(namep, pwd->pw_passwd)) {
+                       error("Password incorrect.\n");
+                       exit(1);
+               }
+       }
+       if (chdir(pwd->pw_dir) < 0) {
+               error("No remote directory.\n");
+               exit(1);
+       }
+       (void) write(2, "\0", 1);
+       if (port) {
+               (void) pipe(pv);
+               pid = fork();
+               if (pid == -1)  {
+                       error("Try again.\n");
+                       exit(1);
+               }
+               if (pid) {
+                       (void) close(0); (void) close(1); (void) close(2);
+                       (void) close(f); (void) close(pv[1]);
+                       readfrom = (1<<s) | (1<<pv[0]);
+                       ioctl(pv[1], FIONBIO, (char *)&one);
+                       /* should set s nbio! */
+                       do {
+                               ready = readfrom;
+                               (void) select(16, (fd_set *)&ready,
+                                   (fd_set *)NULL, (fd_set *)NULL,
+                                   (struct timeval *)NULL);
+                               if (ready & (1<<s)) {
+                                       if (read(s, &sig, 1) <= 0)
+                                               readfrom &= ~(1<<s);
+                                       else
+                                               killpg(pid, sig);
+                               }
+                               if (ready & (1<<pv[0])) {
+                                       cc = read(pv[0], buf, sizeof (buf));
+                                       if (cc <= 0) {
+                                               shutdown(s, 1+1);
+                                               readfrom &= ~(1<<pv[0]);
+                                       } else
+                                               (void) write(s, buf, cc);
+                               }
+                       } while (readfrom);
+                       exit(0);
+               }
+               setpgrp(0, getpid());
+               (void) close(s); (void)close(pv[0]);
+               dup2(pv[1], 2);
+       }
+       if (*pwd->pw_shell == '\0')
+               pwd->pw_shell = _PATH_BSHELL;
+       if (f > 2)
+               (void) close(f);
+       (void) setgid((gid_t)pwd->pw_gid);
+       initgroups(pwd->pw_name, pwd->pw_gid);
+       (void) setuid((uid_t)pwd->pw_uid);
+       (void)strcat(path, _PATH_DEFPATH);
+       environ = envinit;
+       strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
+       strncat(shell, pwd->pw_shell, sizeof(shell)-7);
+       strncat(username, pwd->pw_name, sizeof(username)-6);
+       cp = strrchr(pwd->pw_shell, '/');
+       if (cp)
+               cp++;
+       else
+               cp = pwd->pw_shell;
+       execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
+       perror(pwd->pw_shell);
+       exit(1);
+}
+
+/*VARARGS1*/
+error(fmt, a1, a2, a3)
+       char *fmt;
+       int a1, a2, a3;
+{
+       char buf[BUFSIZ];
+
+       buf[0] = 1;
+       (void) sprintf(buf+1, fmt, a1, a2, a3);
+       (void) write(2, buf, strlen(buf));
+}
+
+getstr(buf, cnt, err)
+       char *buf;
+       int cnt;
+       char *err;
+{
+       char c;
+
+       do {
+               if (read(0, &c, 1) != 1)
+                       exit(1);
+               *buf++ = c;
+               if (--cnt == 0) {
+                       error("%s too long\n", err);
+                       exit(1);
+               }
+       } while (c != 0);
+}
diff --git a/rlogin.tproj/Makefile b/rlogin.tproj/Makefile
new file mode 100644 (file)
index 0000000..bd0c481
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rlogin
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = krb.h
+
+CFILES = des_rw.c kcmd.c krcmd.c rlogin.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rlogin.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DCRYPT
+WINDOWS_PB_CFLAGS = -DCRYPT
+PDO_UNIX_PB_CFLAGS = -DCRYPT
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rlogin.tproj/Makefile.postamble b/rlogin.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..acddb30
--- /dev/null
@@ -0,0 +1 @@
+INSTALL_PERMISSIONS = 4755    # If set, 'install' chmod's executable to this
diff --git a/rlogin.tproj/Makefile.preamble b/rlogin.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..925a5c7
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/rlogin.tproj/PB.project b/rlogin.tproj/PB.project
new file mode 100644 (file)
index 0000000..2898a5d
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    FILESTABLE = {
+        CLASSES = (); 
+        C_FILES = (); 
+        H_FILES = (krb.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (des_rw.c, kcmd.c, krcmd.c, rlogin.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rlogin.1); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DCRYPT"; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = rlogin; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DCRYPT"; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_MAINNIB = rlogin; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rlogin; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = "-DCRYPT"; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_MAINNIB = rlogin; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rlogin.tproj/des_rw.c b/rlogin.tproj/des_rw.c
new file mode 100644 (file)
index 0000000..4e056cf
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)des_rw.c   8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef CRYPT
+#ifdef KERBEROS
+#include <sys/param.h>
+
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static unsigned char   des_inbuf[10240], storage[10240], *store_ptr;
+static bit_64          *key;
+static u_char          *key_schedule;
+
+/* XXX these should be in a kerberos include file */
+int    krb_net_read __P((int, char *, int));
+#ifdef notdef
+/* XXX too hard to make this work */
+int    des_pcbc_encrypt __P((des_cblock *, des_cblock *, long,
+           des_key_schedule, des_cblock *, int));
+#endif
+
+/*
+ * NB: These routines will not function properly if NBIO
+ *     is set
+ */
+
+/*
+ * des_set_key
+ *
+ * Set des encryption/decryption key for use by the des_read and
+ * des_write routines
+ *
+ * The inkey parameter is actually the DES initial vector,
+ * and the insched is the DES Key unwrapped for faster decryption
+ */
+
+void
+des_set_key(inkey, insched)
+       bit_64          *inkey;
+       u_char          *insched;
+{
+       key = inkey;
+       key_schedule = insched;
+}
+
+void
+des_clear_key()
+{
+       bzero((char *) key, sizeof(C_Block));
+       bzero((char *) key_schedule, sizeof(Key_schedule));
+}
+       
+
+int
+des_read(fd, buf, len)
+       int fd;
+       register char *buf;
+       int len;
+{
+       int nreturned = 0;
+       long net_len, rd_len;
+       int nstored = 0;
+
+       if (nstored >= len) {
+               (void) bcopy(store_ptr, buf, len);
+               store_ptr += len;
+               nstored -= len;
+               return(len);
+       } else if (nstored) {
+               (void) bcopy(store_ptr, buf, nstored);
+               nreturned += nstored;
+               buf += nstored;
+               len -= nstored;
+               nstored = 0;
+       }
+       
+       if (krb_net_read(fd, (char *)&net_len, sizeof(net_len)) !=
+           sizeof(net_len)) {
+               /* XXX can't read enough, pipe
+                  must have closed */
+               return(0);
+       }
+       net_len = ntohl(net_len);
+       if (net_len <= 0 || net_len > sizeof(des_inbuf)) {
+               /* preposterous length; assume out-of-sync; only
+                  recourse is to close connection, so return 0 */
+               return(0);
+       }
+       /* the writer tells us how much real data we are getting, but
+          we need to read the pad bytes (8-byte boundary) */
+       rd_len = roundup(net_len, 8);
+       if (krb_net_read(fd, (char *)des_inbuf, rd_len) != rd_len) {
+               /* pipe must have closed, return 0 */
+               return(0);
+       }
+       (void) des_pcbc_encrypt(des_inbuf,      /* inbuf */
+                           storage,            /* outbuf */
+                           net_len,            /* length */
+                           key_schedule,       /* DES key */
+                           key,                /* IV */
+                           DECRYPT);           /* direction */
+
+       if(net_len < 8)
+               store_ptr = storage + 8 - net_len;
+       else
+               store_ptr = storage;
+
+       nstored = net_len;
+       if (nstored > len) {
+               (void) bcopy(store_ptr, buf, len);
+               nreturned += len;
+               store_ptr += len;
+               nstored -= len;
+       } else {
+               (void) bcopy(store_ptr, buf, nstored);
+               nreturned += nstored;
+               nstored = 0;
+       }
+       
+       return(nreturned);
+}
+
+static unsigned char des_outbuf[10240];        /* > longest write */
+
+int
+des_write(fd, buf, len)
+       int fd;
+       char *buf;
+       int len;
+{
+       static  int     seeded = 0;
+       static  char    garbage_buf[8];
+       long net_len, garbage;
+
+       if(len < 8) {
+               if(!seeded) {
+                       seeded = 1;
+                       srandom((int) time((long *)0));
+               }
+               garbage = random();
+               /* insert random garbage */
+               (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8));
+               /* this "right-justifies" the data in the buffer */
+               (void) bcopy(buf, garbage_buf + 8 - len, len);
+       }
+       /* pcbc_encrypt outputs in 8-byte (64 bit) increments */
+
+       (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
+                           des_outbuf,
+                           (len < 8) ? 8 : len,
+                           key_schedule,       /* DES key */
+                           key,                /* IV */
+                           ENCRYPT);
+
+       /* tell the other end the real amount, but send an 8-byte padded
+          packet */
+       net_len = htonl(len);
+       (void) write(fd, &net_len, sizeof(net_len));
+       (void) write(fd, des_outbuf, roundup(len,8));
+       return(len);
+}
+#endif /* KERBEROS */
+#endif /* CRYPT */
diff --git a/rlogin.tproj/kcmd.c b/rlogin.tproj/kcmd.c
new file mode 100644 (file)
index 0000000..1482dda
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(__APPLE__) || defined(KERBEROS)
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include <kerberosIV/kparse.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "krb.h"
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#define        START_PORT      5120     /* arbitrary */
+
+int    getport __P((int *));
+
+int
+kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
+    cred, schedule, msg_data, laddr, faddr, authopts)
+       int *sock;
+       char **ahost;
+       u_short rport;
+       char *locuser, *remuser, *cmd;
+       int *fd2p;
+       KTEXT ticket;
+       char *service;
+       char *realm;
+       CREDENTIALS *cred;
+       Key_schedule schedule;
+       MSG_DAT *msg_data;
+       struct sockaddr_in *laddr, *faddr;
+       long authopts;
+{
+       int s, timo = 1, pid;
+       long oldmask;
+       struct sockaddr_in sin, from;
+       char c;
+#ifdef ATHENA_COMPAT
+       int lport = IPPORT_RESERVED - 1;
+#else
+       int lport = START_PORT;
+#endif
+       struct hostent *hp;
+       int rc;
+       char *host_save;
+       int status;
+
+       pid = getpid();
+       hp = gethostbyname(*ahost);
+       if (hp == NULL) {
+               /* fprintf(stderr, "%s: unknown host\n", *ahost); */
+               return (-1);
+       }
+
+       host_save = malloc(strlen(hp->h_name) + 1);
+       strcpy(host_save, hp->h_name);
+       *ahost = host_save;
+
+#ifdef KERBEROS
+       /* If realm is null, look up from table */
+       if (realm == NULL || realm[0] == '\0')
+               realm = krb_realmofhost(host_save);
+#endif /* KERBEROS */
+
+       oldmask = sigblock(sigmask(SIGURG));
+       for (;;) {
+               s = getport(&lport);
+               if (s < 0) {
+                       if (errno == EAGAIN)
+                               fprintf(stderr,
+                                       "kcmd(socket): All ports in use\n");
+                       else
+                               perror("kcmd: socket");
+                       sigsetmask(oldmask);
+                       return (-1);
+               }
+               fcntl(s, F_SETOWN, pid);
+               sin.sin_family = hp->h_addrtype;
+#if defined(ultrix) || defined(sun)
+               bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
+#else
+               bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
+#endif
+               sin.sin_port = rport;
+               if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+                       break;
+               (void) close(s);
+               if (errno == EADDRINUSE) {
+                       lport--;
+                       continue;
+               }
+               /*
+                * don't wait very long for Kerberos rcmd.
+                */
+               if (errno == ECONNREFUSED && timo <= 4) {
+                       /* sleep(timo); don't wait at all here */
+                       timo *= 2;
+                       continue;
+               }
+#if !(defined(ultrix) || defined(sun))
+               if (hp->h_addr_list[1] != NULL) {
+                       int oerrno = errno;
+
+                       fprintf(stderr,
+                           "kcmd: connect to address %s: ",
+                           inet_ntoa(sin.sin_addr));
+                       errno = oerrno;
+                       perror(NULL);
+                       hp->h_addr_list++;
+                       bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
+                           hp->h_length);
+                       fprintf(stderr, "Trying %s...\n",
+                               inet_ntoa(sin.sin_addr));
+                       continue;
+               }
+#endif /* !(defined(ultrix) || defined(sun)) */
+               if (errno != ECONNREFUSED)
+                       perror(hp->h_name);
+               sigsetmask(oldmask);
+               return (-1);
+       }
+       lport--;
+       if (fd2p == 0) {
+               write(s, "", 1);
+               lport = 0;
+       } else {
+               char num[8];
+               int s2 = getport(&lport), s3;
+               int len = sizeof(from);
+
+               if (s2 < 0) {
+                       status = -1;
+                       goto bad;
+               }
+               listen(s2, 1);
+               (void) sprintf(num, "%d", lport);
+               if (write(s, num, strlen(num) + 1) != strlen(num) + 1) {
+                       perror("kcmd(write): setting up stderr");
+                       (void) close(s2);
+                       status = -1;
+                       goto bad;
+               }
+               s3 = accept(s2, (struct sockaddr *)&from, &len);
+               (void) close(s2);
+               if (s3 < 0) {
+                       perror("kcmd:accept");
+                       lport = 0;
+                       status = -1;
+                       goto bad;
+               }
+               *fd2p = s3;
+               from.sin_port = ntohs((u_short)from.sin_port);
+               if (from.sin_family != AF_INET ||
+                   from.sin_port >= IPPORT_RESERVED) {
+                       fprintf(stderr,
+                        "kcmd(socket): protocol failure in circuit setup.\n");
+                       status = -1;
+                       goto bad2;
+               }
+       }
+       /*
+        * Kerberos-authenticated service.  Don't have to send locuser,
+        * since its already in the ticket, and we'll extract it on
+        * the other side.
+        */
+       /* (void) write(s, locuser, strlen(locuser)+1); */
+
+       /* set up the needed stuff for mutual auth, but only if necessary */
+       if (authopts & KOPT_DO_MUTUAL) {
+               int sin_len;
+               *faddr = sin;
+
+               sin_len = sizeof(struct sockaddr_in);
+               if (getsockname(s, (struct sockaddr *)laddr, &sin_len) < 0) {
+                       perror("kcmd(getsockname)");
+                       status = -1;
+                       goto bad2;
+               }
+       }
+#ifdef KERBEROS
+       if ((status = krb_sendauth(authopts, s, ticket, service, *ahost,
+                              realm, (unsigned long) getpid(), msg_data,
+                              cred, schedule,
+                              laddr,
+                              faddr,
+                              "KCMDV0.1")) != KSUCCESS)
+               goto bad2;
+#endif /* KERBEROS */
+
+       (void) write(s, remuser, strlen(remuser)+1);
+       (void) write(s, cmd, strlen(cmd)+1);
+
+       if ((rc = read(s, &c, 1)) != 1) {
+               if (rc == -1)
+                       perror(*ahost);
+               else
+                       fprintf(stderr,"kcmd: bad connection with remote host\n");
+               status = -1;
+               goto bad2;
+       }
+       if (c != '\0') {
+               while (read(s, &c, 1) == 1) {
+                       (void) write(2, &c, 1);
+                       if (c == '\n')
+                               break;
+               }
+               status = -1;
+               goto bad2;
+       }
+       sigsetmask(oldmask);
+       *sock = s;
+       return (KSUCCESS);
+bad2:
+       if (lport)
+               (void) close(*fd2p);
+bad:
+       (void) close(s);
+       sigsetmask(oldmask);
+       return (status);
+}
+
+int
+getport(alport)
+       int *alport;
+{
+       struct sockaddr_in sin;
+       int s;
+
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = INADDR_ANY;
+       s = socket(AF_INET, SOCK_STREAM, 0);
+       if (s < 0)
+               return (-1);
+       for (;;) {
+               sin.sin_port = htons((u_short)*alport);
+               if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+                       return (s);
+               if (errno != EADDRINUSE) {
+                       (void) close(s);
+                       return (-1);
+               }
+               (*alport)--;
+#ifdef ATHENA_COMPAT
+               if (*alport == IPPORT_RESERVED/2) {
+#else
+               if (*alport == IPPORT_RESERVED) {
+#endif
+                       (void) close(s);
+                       errno = EAGAIN;         /* close */
+                       return (-1);
+               }
+       }
+}
+
+#endif /* !NeXT || KERBEROS */
diff --git a/rlogin.tproj/krb.h b/rlogin.tproj/krb.h
new file mode 100644 (file)
index 0000000..10b6dca
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)krb.h       8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * XXX
+ * These should be in a kerberos include file.
+ */
+void    des_clear_key __P(());
+int     des_read __P((int, char *, int));
+void    des_set_key __P((C_Block, Key_schedule));
+int     des_write __P((int, char *, int));
+int     krb_net_read __P((int, char *, int));
+char   *krb_realmofhost __P((char *));
+int     krb_sendauth __P((long, int, KTEXT, char *, char *, char *,
+           u_long, MSG_DAT *, CREDENTIALS *, Key_schedule,
+           struct sockaddr_in *, struct sockaddr_in *, char *));
+int     krcmd __P((char **, u_short, char *, char *, int *, char *));
+int     krcmd_mutual __P((char **, u_short, char *, char *, int *,
+           char *, CREDENTIALS *, Key_schedule));
diff --git a/rlogin.tproj/krcmd.c b/rlogin.tproj/krcmd.c
new file mode 100644 (file)
index 0000000..cdbba26
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ *     $Source: /cvs/Darwin/Commands/NeXT/network_cmds/rlogin.tproj/krcmd.c,v $
+ *     $Header: /mit/kerberos/ucb/mit/kcmd/RCS/krcmd.c,v 5.1
+ *             89/07/25 15:38:44 kfall Exp Locker: kfall $
+ * static char *rcsid_kcmd_c =
+ * "$Header: /mit/kerberos/ucb/mit/kcmd/RCS/krcmd.c,v 5.1 89/07/25 15:38:44
+ *     kfall Exp Locker: kfall $";
+ */
+
+#ifdef KERBEROS
+#include <sys/types.h>
+#ifdef CRYPT
+#include <sys/socket.h>
+#endif
+
+#include <netinet/in.h>
+
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+#include <stdio.h>
+
+#define        SERVICE_NAME    "rcmd"
+
+int    kcmd __P((int *, char **, u_short, char *, char *, char *, int *,
+           KTEXT, char *, char *, CREDENTIALS *, Key_schedule, MSG_DAT *,
+           struct sockaddr_in *, struct sockaddr_in *, long));
+
+/*
+ * krcmd: simplified version of Athena's "kcmd"
+ *     returns a socket attached to the destination, -1 or krb error on error 
+ *     if fd2p is non-NULL, another socket is filled in for it
+ */
+
+int
+krcmd(ahost, rport, remuser, cmd, fd2p, realm)
+       char    **ahost;
+       u_short rport;
+       char    *remuser, *cmd;
+       int     *fd2p;
+       char    *realm;
+{
+       int             sock = -1, err = 0;
+       KTEXT_ST        ticket;
+       long            authopts = 0L;
+
+       err = kcmd(
+               &sock,
+               ahost,
+               rport,
+               NULL,   /* locuser not used */
+               remuser,
+               cmd,
+               fd2p,
+               &ticket,
+               SERVICE_NAME,
+               realm,
+               (CREDENTIALS *)  NULL,          /* credentials not used */
+               (bit_64 *) NULL,                /* key schedule not used */
+               (MSG_DAT *) NULL,               /* MSG_DAT not used */
+               (struct sockaddr_in *) NULL,    /* local addr not used */
+               (struct sockaddr_in *) NULL,    /* foreign addr not used */
+               authopts
+       );
+
+       if (err > KSUCCESS && err < MAX_KRB_ERRORS) {
+               fprintf(stderr, "krcmd: %s\n", krb_err_txt[err]);
+               return(-1);
+       }
+       if (err < 0)
+               return(-1);
+       return(sock);
+}
+
+#ifdef CRYPT
+int
+krcmd_mutual(ahost, rport, remuser, cmd, fd2p, realm, cred, sched)
+       char            **ahost;
+       u_short         rport;
+       char            *remuser, *cmd;
+       int             *fd2p;
+       char            *realm;
+       CREDENTIALS     *cred;
+       Key_schedule    sched;
+{
+       int             sock, err;
+       KTEXT_ST        ticket;
+       MSG_DAT         msg_dat;
+       struct sockaddr_in      laddr, faddr;
+       long authopts = KOPT_DO_MUTUAL;
+
+       err = kcmd(
+               &sock,
+               ahost,
+               rport,
+               NULL,   /* locuser not used */
+               remuser,
+               cmd,
+               fd2p,
+               &ticket,
+               SERVICE_NAME,
+               realm,
+               cred,           /* filled in */
+               sched,          /* filled in */
+               &msg_dat,       /* filled in */
+               &laddr,         /* filled in */
+               &faddr,         /* filled in */
+               authopts
+       );
+
+       if (err > KSUCCESS && err < MAX_KRB_ERRORS) {
+               fprintf(stderr, "krcmd_mutual: %s\n", krb_err_txt[err]);
+               return(-1);
+       }
+
+       if (err < 0)
+               return (-1);
+       return(sock);
+}
+#endif /* CRYPT */
+#endif /* KERBEROS */
diff --git a/rlogin.tproj/rlogin.1 b/rlogin.tproj/rlogin.1
new file mode 100644 (file)
index 0000000..979658a
--- /dev/null
@@ -0,0 +1,188 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)rlogin.1    8.2 (Berkeley) 4/29/95
+.\"
+.Dd April 29, 1995
+.Dt RLOGIN 1
+.Os BSD 4.2
+.Sh NAME
+.Nm rlogin
+.Nd remote login
+.Sh SYNOPSIS
+.Nm rlogin
+.Op Fl 8EKLdx
+.Op Fl e Ar char
+.Op Fl k Ar realm
+.Op Fl l Ar username
+.Ar host
+.Nm rlogin
+.Op Fl 8EKLdx
+.Op Fl e Ar char
+.Op Fl k Ar realm
+.Ar username@host
+.Sh DESCRIPTION
+.Nm Rlogin
+starts a terminal session on a remote host
+.Ar host  .
+.Pp
+.Nm Rlogin
+first attempts to use the Kerberos authorization mechanism, described below.
+If the remote host does not supporting Kerberos the standard Berkeley
+.Pa rhosts
+authorization mechanism is used.
+The options are as follows:
+.Bl -tag -width flag
+.It Fl 8
+The
+.Fl 8
+option allows an eight-bit input data path at all times; otherwise
+parity bits are stripped except when the remote side's stop and start
+characters are other than
+^S/^Q .
+.It Fl E
+The
+.Fl E
+option stops any character from being recognized as an escape character.
+When used with the
+.Fl 8
+option, this provides a completely transparent connection.
+.It Fl K
+The
+.Fl K
+option turns off all Kerberos authentication.
+.It Fl L
+The
+.Fl L
+option allows the rlogin session to be run in ``litout'' (see
+.Xr tty 4 )
+mode.
+.It Fl d
+The
+.Fl d
+option turns on socket debugging (see
+.Xr setsockopt 2 )
+on the TCP sockets used for communication with the remote host.
+.It Fl e
+The
+.Fl e
+option allows user specification of the escape character, which is
+``~'' by default.
+This specification may be as a literal character, or as an octal
+value in the form \ennn.
+.It Fl k
+The
+.FL k
+option requests rlogin to obtain tickets for the remote host
+in realm
+.Ar realm
+instead of the remote host's realm as determined by
+.Xr krb_realmofhost  3  .
+.It Fl x
+The
+.Fl x
+option turns on
+.Tn DES
+encryption for all data passed via the
+rlogin session.
+This may impact response time and
+.Tn CPU
+utilization, but provides
+increased security.
+.El
+.Pp
+A line of the form ``<escape char>.'' disconnects from the remote host.
+Similarly, the line ``<escape char>^Z'' will suspend the
+.Nm rlogin
+session, and ``<escape char><delayed-suspend char>'' suspends the
+send portion of the rlogin, but allows output from the remote system.
+By default, the tilde (``~'') character is the escape character, and
+normally control-Y (``^Y'') is the delayed-suspend character.
+.Pp
+All echoing takes place at the remote site, so that (except for delays)
+the
+.Nm rlogin
+is transparent.
+Flow control via ^S/^Q and flushing of input and output on interrupts
+are handled properly.
+.Sh KERBEROS AUTHENTICATION
+Each user may have a private authorization list in the file
+.Pa .klogin
+in their home directory.
+Each line in this file should contain a Kerberos principal name of the
+form
+.Ar principal.instance@realm  .
+If the originating user is authenticated to one of the principals named
+in
+.Pa .klogin ,
+access is granted to the account.
+The principal
+.Ar accountname.@localrealm
+is granted access if
+there is no
+.Pa .klogin
+file.
+Otherwise a login and password will be prompted for on the remote machine
+as in
+.Xr login  1  .
+To avoid certain security problems, the
+.Pa .klogin
+file must be owned by
+the remote user.
+.Pp
+If Kerberos authentication fails, a warning message is printed and the
+standard Berkeley
+.Nm rlogin
+is used instead.
+.Sh ENVIRONMENT
+The following environment variable is utilized by
+.Nm rlogin :
+.Bl -tag -width TERM
+.It Ev TERM
+Determines the user's terminal type.
+.El
+.Sh SEE ALSO
+.Xr rsh 1 ,
+.Xr kerberos 3 ,
+.Xr krb_sendauth 3 ,
+.Xr krb_realmofhost 3
+.Sh HISTORY
+The
+.Nm rlogin
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+.Nm Rlogin
+will be replaced by
+.Xr telnet  1
+in the near future.
+.Pp
+More of the environment should be propagated.
diff --git a/rlogin.tproj/rlogin.c b/rlogin.tproj/rlogin.c
new file mode 100644 (file)
index 0000000..b819699
--- /dev/null
@@ -0,0 +1,1011 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * rlogin - remote login
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+#include "krb.h"
+
+CREDENTIALS cred;
+Key_schedule schedule;
+int use_kerberos = 1, doencrypt;
+char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
+#endif
+
+#ifndef TIOCPKT_WINDOW
+#define        TIOCPKT_WINDOW  0x80
+#endif
+
+/* concession to Sun */
+#ifndef SIGUSR1
+#define        SIGUSR1 30
+#endif
+
+int eight, litout, rem;
+
+int noescape;
+u_char escapechar = '~';
+
+#ifdef OLDSUN
+struct winsize {
+       unsigned short ws_row, ws_col;
+       unsigned short ws_xpixel, ws_ypixel;
+};
+#else
+#define        get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp)
+#endif
+struct winsize winsize;
+
+void           catch_child __P((int));
+void           copytochild __P((int));
+__dead void    doit __P((sigset_t *));
+__dead void    done __P((int));
+void           echo __P((char));
+u_int          getescape __P((char *));
+static void    do_exit __P((int));
+void           lostpeer __P((int));
+void           mode __P((int));
+void           msg __P((char *));
+void           oob __P((int));
+int            reader __P((sigset_t *));
+void           sendwindow __P((void));
+void           setsignal __P((int));
+int            speed __P((int));
+void           sigwinch __P((int));
+void           stop __P((char));
+__dead void    usage __P((void));
+void           writer __P((void));
+void           writeroob __P((int));
+
+#ifdef KERBEROS
+void           warning __P((const char *, ...));
+#endif
+#ifdef OLDSUN
+int            get_window_size __P((int, struct winsize *));
+#endif
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct passwd *pw;
+       struct servent *sp;
+       sigset_t smask;
+       uid_t uid;
+       int argoff, ch, dflag, one;
+       char *host, *p, *user, term[1024];
+       struct sigaction sa;
+
+       argoff = dflag = 0;
+       one = 1;
+       host = user = NULL;
+
+       if (p = strrchr(argv[0], '/'))
+               ++p;
+       else
+               p = argv[0];
+
+       if (strcmp(p, "rlogin") != 0)
+               host = p;
+
+       /* handle "rlogin host flags" */
+       if (!host && argc > 2 && argv[1][0] != '-') {
+               host = argv[1];
+               argoff = 1;
+       }
+
+#ifdef KERBEROS
+#define        OPTIONS "8EKLde:k:l:x"
+#else
+#define        OPTIONS "8EKLde:l:"
+#endif
+       while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
+               switch(ch) {
+               case '8':
+                       eight = 1;
+                       break;
+               case 'E':
+                       noescape = 1;
+                       break;
+               case 'K':
+#ifdef KERBEROS
+                       use_kerberos = 0;
+#endif
+                       break;
+               case 'L':
+                       litout = 1;
+                       break;
+               case 'd':
+                       dflag = 1;
+                       break;
+               case 'e':
+                       noescape = 0;
+                       escapechar = getescape(optarg);
+                       break;
+#ifdef KERBEROS
+               case 'k':
+                       dest_realm = dst_realm_buf;
+                       (void)strncpy(dest_realm, optarg, REALM_SZ);
+                       break;
+#endif
+               case 'l':
+                       user = optarg;
+                       break;
+#ifdef CRYPT
+#ifdef KERBEROS
+               case 'x':
+                       doencrypt = 1;
+                       des_set_key(cred.session, schedule);
+                       break;
+#endif
+#endif
+               case '?':
+               default:
+                       usage();
+               }
+       optind += argoff;
+       argc -= optind;
+       argv += optind;
+
+       /* if haven't gotten a host yet, do so */
+       if (!host && !(host = *argv++))
+               usage();
+
+       if (*argv)
+               usage();
+
+       if (!(pw = getpwuid(uid = getuid())))
+               errx(1, "unknown user id.");
+       /* Accept user1@host format, though "-l user2" overrides user1 */
+       p = strchr(host, '@');
+       if (p) {
+               *p = '\0';
+               if (!user && p > host)
+                       user = host;
+               host = p + 1;
+               if (*host == '\0')
+                       usage();
+       }
+       if (!user)
+               user = pw->pw_name;
+
+       sp = NULL;
+#ifdef KERBEROS
+       if (use_kerberos) {
+               sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp");
+               if (sp == NULL) {
+                       use_kerberos = 0;
+                       warning("can't get entry for %s/tcp service",
+                           doencrypt ? "eklogin" : "klogin");
+               }
+       }
+#endif
+       if (sp == NULL)
+               sp = getservbyname("login", "tcp");
+       if (sp == NULL)
+               errx(1, "login/tcp: unknown service.");
+
+       (void)snprintf(term, sizeof(term), "%s/%d",
+                       ((p = getenv("TERM")) ? p : "network"),
+                       speed(0));
+
+       (void)get_window_size(0, &winsize);
+
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_RESTART;
+       sa.sa_handler = lostpeer;
+       (void)sigaction(SIGPIPE, &sa, (struct sigaction *) 0);
+       /* will use SIGUSR1 for window size hack, so hold it off */
+       sigemptyset(&smask);
+       sigaddset(&smask, SIGURG);
+       sigaddset(&smask, SIGUSR1);
+       (void)sigprocmask(SIG_SETMASK, &smask, &smask);
+       /*
+        * We set SIGURG and SIGUSR1 below so that an
+        * incoming signal will be held pending rather than being
+        * discarded. Note that these routines will be ready to get
+        * a signal by the time that they are unblocked below.
+        */
+       sa.sa_handler = copytochild;
+       (void)sigaction(SIGURG, &sa, (struct sigaction *) 0);
+       sa.sa_handler = writeroob;
+       (void)sigaction(SIGUSR1, &sa, (struct sigaction *) 0);
+
+#ifdef KERBEROS
+try_connect:
+       if (use_kerberos) {
+               struct hostent *hp;
+
+               /* Fully qualify hostname (needed for krb_realmofhost). */
+               hp = gethostbyname(host);
+               if (hp != NULL && !(host = strdup(hp->h_name)))
+                       errx(1, "%s", strerror(ENOMEM));
+
+               rem = KSUCCESS;
+               errno = 0;
+               if (dest_realm == NULL)
+                       dest_realm = krb_realmofhost(host);
+
+#ifdef CRYPT
+               if (doencrypt)
+                       rem = krcmd_mutual(&host, sp->s_port, user, term, 0,
+                           dest_realm, &cred, schedule);
+               else
+#endif /* CRYPT */
+                       rem = krcmd(&host, sp->s_port, user, term, 0,
+                           dest_realm);
+               if (rem < 0) {
+                       use_kerberos = 0;
+                       sp = getservbyname("login", "tcp");
+                       if (sp == NULL)
+                               errx(1, "unknown service login/tcp.");
+                       if (errno == ECONNREFUSED)
+                               warning("remote host doesn't support Kerberos");
+                       if (errno == ENOENT)
+                               warning("can't provide Kerberos auth data");
+                       goto try_connect;
+               }
+       } else {
+#ifdef CRYPT
+               if (doencrypt)
+                       errx(1, "the -x flag requires Kerberos authentication.");
+#endif /* CRYPT */
+               rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
+       }
+#else
+       rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
+#endif /* KERBEROS */
+
+       if (rem < 0)
+               exit(1);
+
+       if (dflag &&
+           setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0)
+               warn("setsockopt DEBUG (ignored)");
+       one = IPTOS_LOWDELAY;
+       if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0)
+               warn("setsockopt TOS (ignored)");
+
+       (void)setuid(uid);
+       doit(&smask);
+       /*NOTREACHED*/
+}
+
+#if BSD >= 198810
+int
+speed(fd)
+       int fd;
+{
+       struct termios tt;
+
+       (void)tcgetattr(fd, &tt);
+
+       return ((int) cfgetispeed(&tt));
+}
+#else
+int    speeds[] = {    /* for older systems, B0 .. EXTB */
+       0, 50, 75, 110,
+       134, 150, 200, 300,
+       600, 1200, 1800, 2400,
+       4800, 9600, 19200, 38400
+};
+
+int
+speed(fd)
+       int fd;
+{
+       struct termios tt;
+
+       (void)tcgetattr(fd, &tt);
+
+       return (speeds[(int)cfgetispeed(&tt)]);
+}
+#endif
+
+pid_t child;
+struct termios deftt;
+struct termios nott;
+
+void
+doit(smask)
+       sigset_t *smask;
+{
+       int i;
+       struct sigaction sa;
+
+       for (i = 0; i < NCCS; i++)
+               nott.c_cc[i] = _POSIX_VDISABLE;
+       tcgetattr(0, &deftt);
+       nott.c_cc[VSTART] = deftt.c_cc[VSTART];
+       nott.c_cc[VSTOP] = deftt.c_cc[VSTOP];
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_RESTART;
+       sa.sa_handler = SIG_IGN;
+       (void)sigaction(SIGINT, &sa, (struct sigaction *) 0);
+       setsignal(SIGHUP);
+       setsignal(SIGQUIT);
+       child = fork();
+       if (child == -1) {
+               warn("fork");
+               done(1);
+       }
+       if (child == 0) {
+               mode(1);
+               if (reader(smask) == 0) {
+                       msg("connection closed.");
+                       exit(0);
+               }
+               sleep(1);
+               msg("\007connection closed.");
+               exit(1);
+       }
+
+       /*
+        * We may still own the socket, and may have a pending SIGURG (or might
+        * receive one soon) that we really want to send to the reader.  When
+        * one of these comes in, the trap copytochild simply copies such
+        * signals to the child. We can now unblock SIGURG and SIGUSR1
+        * that were set above.
+        */
+       (void)sigprocmask(SIG_SETMASK, smask, (sigset_t *) 0);
+       sa.sa_handler = catch_child;
+       (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
+       writer();
+       msg("closed connection.");
+       done(0);
+}
+
+/* trap a signal, unless it is being ignored. */
+void
+setsignal(sig)
+       int sig;
+{
+       struct sigaction sa;
+       sigset_t sigs;
+
+       sigemptyset(&sigs);
+       sigaddset(&sigs, sig);
+       sigprocmask(SIG_BLOCK, &sigs, &sigs);
+
+       sigemptyset(&sa.sa_mask);
+       sa.sa_handler = do_exit;
+       sa.sa_flags = SA_RESTART;
+       (void)sigaction(sig, &sa, &sa);
+       if (sa.sa_handler == SIG_IGN)
+               (void)sigaction(sig, &sa, (struct sigaction *) 0);
+
+       (void)sigprocmask(SIG_SETMASK, &sigs, (sigset_t *) 0);
+}
+
+__dead void
+done(status)
+       int status;
+{
+       pid_t w;
+       int wstatus;
+       struct sigaction sa;
+
+       mode(0);
+       if (child > 0) {
+               /* make sure catch_child does not snap it up */
+               sigemptyset(&sa.sa_mask);
+               sa.sa_handler = SIG_DFL;
+               sa.sa_flags = 0;
+               (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
+               if (kill(child, SIGKILL) >= 0)
+                       while ((w = wait(&wstatus)) > 0 && w != child)
+                               continue;
+       }
+       exit(status);
+}
+
+int dosigwinch;
+
+/*
+ * This is called when the reader process gets the out-of-band (urgent)
+ * request to turn on the window-changing protocol.
+ */
+void
+writeroob(signo)
+       int signo;
+{
+       struct sigaction sa;
+
+       if (dosigwinch == 0) {
+               sendwindow();
+               sigemptyset(&sa.sa_mask);
+               sa.sa_handler = sigwinch;
+               sa.sa_flags = SA_RESTART;
+               (void)sigaction(SIGWINCH, &sa, (struct sigaction *) 0);
+       }
+       dosigwinch = 1;
+}
+
+void
+catch_child(signo)
+       int signo;
+{
+       int status;
+       pid_t pid;
+
+       for (;;) {
+               pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
+               if (pid == 0)
+                       return;
+               /* if the child (reader) dies, just quit */
+               if (pid < 0 || (pid == child && !WIFSTOPPED(status)))
+                       done(WEXITSTATUS(status) | WTERMSIG(status));
+       }
+       /* NOTREACHED */
+}
+
+/*
+ * writer: write to remote: 0 -> line.
+ * ~.                          terminate
+ * ~^Z                         suspend rlogin process.
+ * ~<delayed-suspend char>     suspend rlogin process, but leave reader alone.
+ */
+void
+writer()
+{
+       register int bol, local, n;
+       char c;
+
+       bol = 1;                        /* beginning of line */
+       local = 0;
+       for (;;) {
+               n = read(STDIN_FILENO, &c, 1);
+               if (n <= 0) {
+                       if (n < 0 && errno == EINTR)
+                               continue;
+                       break;
+               }
+               /*
+                * If we're at the beginning of the line and recognize a
+                * command character, then we echo locally.  Otherwise,
+                * characters are echo'd remotely.  If the command character
+                * is doubled, this acts as a force and local echo is
+                * suppressed.
+                */
+               if (bol) {
+                       bol = 0;
+                       if (!noescape && c == escapechar) {
+                               local = 1;
+                               continue;
+                       }
+               } else if (local) {
+                       local = 0;
+                       if (c == '.' || c == deftt.c_cc[VEOF]) {
+                               echo(c);
+                               break;
+                       }
+                       if (c == deftt.c_cc[VSUSP] || c == deftt.c_cc[VDSUSP]) {
+                               bol = 1;
+                               echo(c);
+                               stop(c);
+                               continue;
+                       }
+                       if (c != escapechar)
+#ifdef CRYPT
+#ifdef KERBEROS
+                               if (doencrypt)
+                                       (void)des_write(rem,
+                                           (char *)&escapechar, 1);
+                               else
+#endif
+#endif
+                                       (void)write(rem, &escapechar, 1);
+               }
+
+#ifdef CRYPT
+#ifdef KERBEROS
+               if (doencrypt) {
+                       if (des_write(rem, &c, 1) == 0) {
+                               msg("line gone");
+                               break;
+                       }
+               } else
+#endif
+#endif
+                       if (write(rem, &c, 1) == 0) {
+                               msg("line gone");
+                               break;
+                       }
+               bol = c == deftt.c_cc[VKILL] || c == deftt.c_cc[VEOF] ||
+                   c == deftt.c_cc[VINTR] || c == deftt.c_cc[VSUSP] ||
+                   c == '\r' || c == '\n';
+       }
+}
+
+void
+#if __STDC__
+echo(register char c)
+#else
+echo(c)
+       register char c;
+#endif
+{
+       register char *p;
+       char buf[8];
+
+       p = buf;
+       c &= 0177;
+       *p++ = escapechar;
+       if (c < ' ') {
+               *p++ = '^';
+               *p++ = c + '@';
+       } else if (c == 0177) {
+               *p++ = '^';
+               *p++ = '?';
+       } else
+               *p++ = c;
+       *p++ = '\r';
+       *p++ = '\n';
+       (void)write(STDOUT_FILENO, buf, p - buf);
+}
+
+void
+#if __STDC__
+stop(char cmdc)
+#else
+stop(cmdc)
+       char cmdc;
+#endif
+{
+       struct sigaction sa;
+
+       mode(0);
+       sigemptyset(&sa.sa_mask);
+       sa.sa_handler = SIG_IGN;
+       sa.sa_flags = SA_RESTART;
+       (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
+       (void)kill(cmdc == deftt.c_cc[VSUSP] ? 0 : getpid(), SIGTSTP);
+       sa.sa_handler = catch_child;
+       (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
+       mode(1);
+       sigwinch(0);                    /* check for size changes */
+}
+
+void
+sigwinch(signo)
+       int signo;
+{
+       struct winsize ws;
+
+       if (dosigwinch && get_window_size(0, &ws) == 0 &&
+           memcmp(&ws, &winsize, sizeof(ws))) {
+               winsize = ws;
+               sendwindow();
+       }
+}
+
+/*
+ * Send the window size to the server via the magic escape
+ */
+void
+sendwindow()
+{
+       struct winsize *wp;
+       char obuf[4 + sizeof (struct winsize)];
+
+       wp = (struct winsize *)(obuf+4);
+       obuf[0] = 0377;
+       obuf[1] = 0377;
+       obuf[2] = 's';
+       obuf[3] = 's';
+       wp->ws_row = htons(winsize.ws_row);
+       wp->ws_col = htons(winsize.ws_col);
+       wp->ws_xpixel = htons(winsize.ws_xpixel);
+       wp->ws_ypixel = htons(winsize.ws_ypixel);
+
+#ifdef CRYPT
+#ifdef KERBEROS
+       if(doencrypt)
+               (void)des_write(rem, obuf, sizeof(obuf));
+       else
+#endif
+#endif
+               (void)write(rem, obuf, sizeof(obuf));
+}
+
+/*
+ * reader: read from remote: line -> 1
+ */
+#define        READING 1
+#define        WRITING 2
+
+jmp_buf rcvtop;
+pid_t ppid;
+int rcvcnt, rcvstate;
+char rcvbuf[8 * 1024];
+
+void
+oob(signo)
+       int signo;
+{
+       struct termios tt;
+       int atmark, n, out, rcvd;
+       char waste[BUFSIZ], mark;
+
+       out = O_RDWR;
+       rcvd = 0;
+       while (recv(rem, &mark, 1, MSG_OOB) < 0) {
+               switch (errno) {
+               case EWOULDBLOCK:
+                       /*
+                        * Urgent data not here yet.  It may not be possible
+                        * to send it yet if we are blocked for output and
+                        * our input buffer is full.
+                        */
+                       if (rcvcnt < sizeof(rcvbuf)) {
+                               n = read(rem, rcvbuf + rcvcnt,
+                                   sizeof(rcvbuf) - rcvcnt);
+                               if (n <= 0)
+                                       return;
+                               rcvd += n;
+                       } else {
+                               n = read(rem, waste, sizeof(waste));
+                               if (n <= 0)
+                                       return;
+                       }
+                       continue;
+               default:
+                       return;
+               }
+       }
+       if (mark & TIOCPKT_WINDOW) {
+               /* Let server know about window size changes */
+               (void)kill(ppid, SIGUSR1);
+       }
+       if (!eight && (mark & TIOCPKT_NOSTOP)) {
+               tcgetattr(0, &tt);
+               tt.c_iflag &= ~(IXON | IXOFF);
+               tt.c_cc[VSTOP] = _POSIX_VDISABLE;
+               tt.c_cc[VSTART] = _POSIX_VDISABLE;
+               tcsetattr(0, TCSANOW, &tt);
+       }
+       if (!eight && (mark & TIOCPKT_DOSTOP)) {
+               tcgetattr(0, &tt);
+               tt.c_iflag |= (IXON|IXOFF);
+               tt.c_cc[VSTOP] = deftt.c_cc[VSTOP];
+               tt.c_cc[VSTART] = deftt.c_cc[VSTART];
+               tcsetattr(0, TCSANOW, &tt);
+       }
+       if (mark & TIOCPKT_FLUSHWRITE) {
+               (void)ioctl(1, TIOCFLUSH, (char *)&out);
+               for (;;) {
+                       if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
+                               warn("ioctl SIOCATMARK (ignored)");
+                               break;
+                       }
+                       if (atmark)
+                               break;
+                       n = read(rem, waste, sizeof (waste));
+                       if (n <= 0)
+                               break;
+               }
+               /*
+                * Don't want any pending data to be output, so clear the recv
+                * buffer.  If we were hanging on a write when interrupted,
+                * don't want it to restart.  If we were reading, restart
+                * anyway.
+                */
+               rcvcnt = 0;
+               longjmp(rcvtop, 1);
+       }
+
+       /* oob does not do FLUSHREAD (alas!) */
+
+       /*
+        * If we filled the receive buffer while a read was pending, longjmp
+        * to the top to restart appropriately.  Don't abort a pending write,
+        * however, or we won't know how much was written.
+        */
+       if (rcvd && rcvstate == READING)
+               longjmp(rcvtop, 1);
+}
+
+/* reader: read from remote: line -> 1 */
+int
+reader(smask)
+       sigset_t *smask;
+{
+       pid_t pid;
+       int n, remaining;
+       char *bufp;
+       struct sigaction sa;
+
+#if BSD >= 43 || defined(SUNOS4)
+       pid = getpid();         /* modern systems use positives for pid */
+#else
+       pid = -getpid();        /* old broken systems use negatives */
+#endif
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_RESTART;
+       sa.sa_handler = SIG_IGN;
+       (void)sigaction(SIGTTOU, &sa, (struct sigaction *) 0);
+       sa.sa_handler = oob;
+       (void)sigaction(SIGURG, &sa, (struct sigaction *) 0);
+       ppid = getppid();
+       (void)fcntl(rem, F_SETOWN, pid);
+       (void)setjmp(rcvtop);
+       (void)sigprocmask(SIG_SETMASK, smask, (sigset_t *) 0);
+       bufp = rcvbuf;
+       for (;;) {
+               while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
+                       rcvstate = WRITING;
+                       n = write(STDOUT_FILENO, bufp, remaining);
+                       if (n < 0) {
+                               if (errno != EINTR)
+                                       return (-1);
+                               continue;
+                       }
+                       bufp += n;
+               }
+               bufp = rcvbuf;
+               rcvcnt = 0;
+               rcvstate = READING;
+
+#ifdef CRYPT
+#ifdef KERBEROS
+               if (doencrypt)
+                       rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf));
+               else
+#endif
+#endif
+                       rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
+               if (rcvcnt == 0)
+                       return (0);
+               if (rcvcnt < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       warn("read");
+                       return (-1);
+               }
+       }
+}
+
+void
+mode(f)
+       int f;
+{
+       struct termios tt;
+
+       switch (f) {
+       case 0:
+               tcsetattr(0, TCSADRAIN, &deftt);
+               break;
+       case 1:
+               tt = deftt;
+               tt.c_oflag &= ~(OPOST);
+               tt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+               tt.c_iflag &= ~(ICRNL);
+               tt.c_cc[VMIN] = 1;
+               tt.c_cc[VTIME] = 0;
+               if (eight) {
+                       tt.c_iflag &= ~(IXON | IXOFF | ISTRIP);
+                       tt.c_cc[VSTOP] = _POSIX_VDISABLE;
+                       tt.c_cc[VSTART] = _POSIX_VDISABLE;
+               }
+               /*if (litout)
+                       lflags |= LLITOUT;*/
+               tcsetattr(0, TCSADRAIN, &tt);
+               break;
+
+       default:
+               return;
+       }
+}
+
+void
+lostpeer(signo)
+       int signo;
+{
+       struct sigaction sa;
+
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_RESTART;
+       sa.sa_handler = SIG_IGN;
+       (void)sigaction(SIGPIPE, &sa, (struct sigaction *) 0);
+       msg("\007connection closed.");
+       done(1);
+}
+
+/* copy SIGURGs to the child process. */
+void
+copytochild(signo)
+       int signo;
+{
+
+       (void)kill(child, SIGURG);
+}
+
+static void do_exit(int signo)
+{
+    exit(signo);
+}
+
+void
+msg(str)
+       char *str;
+{
+
+       (void)fprintf(stderr, "rlogin: %s\r\n", str);
+}
+
+#ifdef KERBEROS
+/* VARARGS */
+void
+#if __STDC__
+warning(const char *fmt, ...)
+#else
+warning(fmt, va_alist)
+       char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "rlogin: warning, using standard rlogin: ");
+#ifdef __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, ".\n");
+}
+#endif
+
+__dead void
+usage()
+{
+       (void)fprintf(stderr,
+           "usage: rlogin [ -%s]%s[-e char] [ -l username ] [username@]host\n",
+#ifdef KERBEROS
+#ifdef CRYPT
+           "8EKLx", " [-k realm] ");
+#else
+           "8EKL", " [-k realm] ");
+#endif
+#else
+           "8EL", " ");
+#endif
+       exit(1);
+}
+
+/*
+ * The following routine provides compatibility (such as it is) between older
+ * Suns and others.  Suns have only a `ttysize', so we convert it to a winsize.
+ */
+#ifdef OLDSUN
+int
+get_window_size(fd, wp)
+       int fd;
+       struct winsize *wp;
+{
+       struct ttysize ts;
+       int error;
+
+       if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
+               return (error);
+       wp->ws_row = ts.ts_lines;
+       wp->ws_col = ts.ts_cols;
+       wp->ws_xpixel = 0;
+       wp->ws_ypixel = 0;
+       return (0);
+}
+#endif
+
+u_int
+getescape(p)
+       register char *p;
+{
+       long val;
+       int len;
+
+       if ((len = strlen(p)) == 1)     /* use any single char, including '\' */
+               return ((u_int)*p);
+                                       /* otherwise, \nnn */
+       if (*p == '\\' && len >= 2 && len <= 4) {
+               val = strtol(++p, NULL, 8);
+               for (;;) {
+                       if (!*++p)
+                               return ((u_int)val);
+                       if (*p < '0' || *p > '8')
+                               break;
+               }
+       }
+       msg("illegal option value -- e");
+       usage();
+       /* NOTREACHED */
+}
diff --git a/rlogind.tproj/Makefile b/rlogind.tproj/Makefile
new file mode 100644 (file)
index 0000000..753d291
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rlogind
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = rlogind.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rlogind.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DCRYPT
+WINDOWS_PB_CFLAGS = -DCRYPT
+PDO_UNIX_PB_CFLAGS = -DCRYPT
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rlogind.tproj/Makefile.postamble b/rlogind.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..046da0d
--- /dev/null
@@ -0,0 +1,2 @@
+VPATH += :../rlogin.tproj
+
diff --git a/rlogind.tproj/Makefile.preamble b/rlogind.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..97bb72e
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_OFILES = des_rw.o
+-include ../Makefile.include
diff --git a/rlogind.tproj/PB.project b/rlogind.tproj/PB.project
new file mode 100644 (file)
index 0000000..20866a4
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (rlogind.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rlogind.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DCRYPT"; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DCRYPT"; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rlogind; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = "-DCRYPT"; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rlogind.tproj/pathnames.h b/rlogind.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..b9a57fa
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ */
+
+#include <paths.h>
+
+#define        _PATH_LOGIN     "/usr/bin/login"
diff --git a/rlogind.tproj/rlogind.8 b/rlogind.tproj/rlogind.8
new file mode 100644 (file)
index 0000000..9c19933
--- /dev/null
@@ -0,0 +1,168 @@
+.\" Copyright (c) 1983, 1989, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)rlogind.8  8.1 (Berkeley) 6/4/93
+.\"
+.Dd June 4, 1993
+.Dt RLOGIND 8
+.Os BSD 4.2
+.Sh NAME
+.Nm rlogind
+.Nd remote login server
+.Sh SYNOPSIS
+.Nm rlogind
+.Op Fl aln
+.Sh DESCRIPTION
+.Nm Rlogind
+is the server for the 
+.Xr rlogin 1
+program.  The server provides a remote login facility
+with authentication based on privileged port numbers from trusted hosts.
+.Pp
+Options supported by
+.Nm rlogind :
+.Bl -tag -width Ds
+.It Fl a
+Ask hostname for verification.
+.It Fl l
+Prevent any authentication based on the user's
+.Dq Pa .rhosts
+file, unless the user is logging in as the superuser.
+.It Fl n
+Disable keep-alive messages.
+.El
+.Pp
+.Nm Rlogind
+listens for service requests at the port indicated in
+the ``login'' service specification; see
+.Xr services 5 .
+When a service request is received the following protocol
+is initiated:
+.Bl -enum
+.It
+The server checks the client's source port.
+If the port is not in the range 512-1023, the server
+aborts the connection.
+.It
+The server checks the client's source address
+and requests the corresponding host name (see
+.Xr gethostbyaddr 3 ,
+.Xr hosts 5
+and
+.Xr named 8 ) .
+If the hostname cannot be determined,
+the dot-notation representation of the host address is used.
+If the hostname is in the same domain as the server (according to
+the last two components of the domain name),
+or if the
+.Fl a
+option is given,
+the addresses for the hostname are requested,
+verifying that the name and address correspond.
+Normal authentication is bypassed if the address verification fails.
+.El
+.Pp
+Once the source port and address have been checked, 
+.Nm rlogind
+proceeds with the authentication process described in
+.Xr rshd 8 .
+It then allocates a pseudo terminal (see 
+.Xr pty 4 ) ,
+and manipulates file descriptors so that the slave
+half of the pseudo terminal becomes the 
+.Em stdin ,
+.Em stdout ,
+and
+.Em stderr
+for a login process.
+The login process is an instance of the
+.Xr login 1
+program, invoked with the
+.Fl f
+option if authentication has succeeded.
+If automatic authentication fails, the user is
+prompted to log in as if on a standard terminal line.
+.Pp
+The parent of the login process manipulates the master side of
+the pseudo terminal, operating as an intermediary
+between the login process and the client instance of the
+.Xr rlogin
+program.  In normal operation, the packet protocol described
+in
+.Xr pty 4
+is invoked to provide
+.Ql ^S/^Q
+type facilities and propagate
+interrupt signals to the remote programs.  The login process
+propagates the client terminal's baud rate and terminal type,
+as found in the environment variable,
+.Ql Ev TERM ;
+see
+.Xr environ 7 .
+The screen or window size of the terminal is requested from the client,
+and window size changes from the client are propagated to the pseudo terminal.
+.Pp
+Transport-level keepalive messages are enabled unless the
+.Fl n
+option is present.
+The use of keepalive messages allows sessions to be timed out
+if the client crashes or becomes unreachable.
+.Sh DIAGNOSTICS
+All initial diagnostic messages are indicated
+by a leading byte with a value of 1,
+after which any network connections are closed.
+If there are no errors before
+.Xr login
+is invoked, a null byte is returned as in indication of success.
+.Bl -tag -width Ds
+.It Sy Try again.
+A
+.Xr fork
+by the server failed.
+.El
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr ruserok 3 ,
+.Xr rshd 8
+.Sh BUGS
+The authentication procedure used here assumes the integrity
+of each client machine and the connecting medium.  This is
+insecure, but is useful in an ``open'' environment.
+.Pp
+A facility to allow all data exchanges to be encrypted should be
+present.
+.Pp
+A more extensible protocol should be used.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/rlogind.tproj/rlogind.c b/rlogind.tproj/rlogind.c
new file mode 100644 (file)
index 0000000..4cb0575
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1983, 1988, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rlogind.c  8.2 (Berkeley) 4/28/95";
+#endif /* not lint */
+
+/*
+ * remote login server:
+ *     \0
+ *     remuser\0
+ *     locuser\0
+ *     terminal_type/speed\0
+ *     data
+ */
+
+#define        FD_SETSIZE      16              /* don't need many bits for select */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#ifdef __APPLE__
+#include <sys/termios.h>
+#else
+#include <termios.h>
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <pwd.h>
+#include <syslog.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pathnames.h"
+
+#ifndef TIOCPKT_WINDOW
+#define TIOCPKT_WINDOW 0x80
+#endif
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#define        SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n"
+
+AUTH_DAT       *kdata;
+KTEXT          ticket;
+u_char         auth_buf[sizeof(AUTH_DAT)];
+u_char         tick_buf[sizeof(KTEXT_ST)];
+Key_schedule   schedule;
+int            doencrypt, retval, use_kerberos, vacuous;
+
+#define                ARGSTR                  "alnkvx"
+#else
+#define                ARGSTR                  "aln"
+#endif /* KERBEROS */
+
+char   *env[2];
+#define        NMAX 30
+char   lusername[NMAX+1], rusername[NMAX+1];
+static char term[64] = "TERM=";
+#define        ENVSIZE (sizeof("TERM=")-1)     /* skip null for concatenation */
+int    keepalive = 1;
+int    check_all = 0;
+
+struct passwd *pwd;
+
+void   doit __P((int, struct sockaddr_in *));
+int    control __P((int, char *, int));
+void   protocol __P((int, int));
+void   cleanup __P((int));
+void   fatal __P((int, char *, int));
+int    do_rlogin __P((struct sockaddr_in *));
+void   getstr __P((char *, int, char *));
+void   setup_term __P((int));
+int    do_krb_login __P((struct sockaddr_in *));
+void   usage __P((void));
+int    local_domain __P((char *));
+char   *topdomain __P((char *));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern int __check_rhosts_file;
+       struct sockaddr_in from;
+       int ch, fromlen, on;
+
+       openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
+
+       opterr = 0;
+       while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
+               switch (ch) {
+               case 'a':
+                       check_all = 1;
+                       break;
+               case 'l':
+                       __check_rhosts_file = 0;
+                       break;
+               case 'n':
+                       keepalive = 0;
+                       break;
+#ifdef KERBEROS
+               case 'k':
+                       use_kerberos = 1;
+                       break;
+               case 'v':
+                       vacuous = 1;
+                       break;
+#ifdef CRYPT
+               case 'x':
+                       doencrypt = 1;
+                       break;
+#endif
+#endif
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+       argc -= optind;
+       argv += optind;
+
+#ifdef KERBEROS
+       if (use_kerberos && vacuous) {
+               usage();
+               fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
+       }
+#endif
+       fromlen = sizeof (from);
+       if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+               syslog(LOG_ERR,"Can't get peer name of remote host: %m");
+               fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
+       }
+       on = 1;
+       if (keepalive &&
+           setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
+               syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+       on = IPTOS_LOWDELAY;
+       if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
+               syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+       doit(0, &from);
+}
+
+int    child;
+int    netf;
+char   line[MAXPATHLEN];
+int    confirmed;
+
+struct winsize win = { 0, 0, 0, 0 };
+
+
+void
+doit(f, fromp)
+       int f;
+       struct sockaddr_in *fromp;
+{
+       int master, pid, on = 1;
+       int authenticated = 0;
+       register struct hostent *hp;
+       char hostname[2 * MAXHOSTNAMELEN + 1];
+       char c;
+
+       alarm(60);
+       read(f, &c, 1);
+
+       if (c != 0)
+               exit(1);
+#ifdef KERBEROS
+       if (vacuous)
+               fatal(f, "Remote host requires Kerberos authentication", 0);
+#endif
+
+       alarm(0);
+       fromp->sin_port = ntohs((u_short)fromp->sin_port);
+       hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr),
+           fromp->sin_family);
+       if (hp)
+               (void)strcpy(hostname, hp->h_name);
+       else
+               (void)strcpy(hostname, inet_ntoa(fromp->sin_addr));
+
+#ifdef KERBEROS
+       if (use_kerberos) {
+               retval = do_krb_login(fromp);
+               if (retval == 0)
+                       authenticated++;
+               else if (retval > 0)
+                       fatal(f, krb_err_txt[retval], 0);
+               write(f, &c, 1);
+               confirmed = 1;          /* we sent the null! */
+       } else
+#endif
+       {
+               if (fromp->sin_family != AF_INET ||
+                   fromp->sin_port >= IPPORT_RESERVED ||
+                   fromp->sin_port < IPPORT_RESERVED/2) {
+                       syslog(LOG_NOTICE, "Connection from %s on illegal port",
+                               inet_ntoa(fromp->sin_addr));
+                       fatal(f, "Permission denied", 0);
+               }
+#ifdef IP_OPTIONS
+               {
+               u_char optbuf[BUFSIZ/3], *cp;
+               char lbuf[BUFSIZ], *lp;
+               int optsize = sizeof(optbuf), ipproto;
+               struct protoent *ip;
+
+               if ((ip = getprotobyname("ip")) != NULL)
+                       ipproto = ip->p_proto;
+               else
+                       ipproto = IPPROTO_IP;
+               if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf,
+                   &optsize) == 0 && optsize != 0) {
+                       lp = lbuf;
+                       for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
+                               sprintf(lp, " %2.2x", *cp);
+                       syslog(LOG_NOTICE,
+                           "Connection received using IP options (ignored):%s",
+                           lbuf);
+                       if (setsockopt(0, ipproto, IP_OPTIONS,
+                           (char *)NULL, optsize) != 0) {
+                               syslog(LOG_ERR,
+                                   "setsockopt IP_OPTIONS NULL: %m");
+                               exit(1);
+                       }
+               }
+               }
+#endif
+               if (do_rlogin(fromp) == 0)
+                       authenticated++;
+       }
+       if (confirmed == 0) {
+               write(f, "", 1);
+               confirmed = 1;          /* we sent the null! */
+       }
+#ifdef KERBEROS
+#ifdef CRYPT
+       if (doencrypt)
+               (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1);
+#endif
+#endif
+       netf = f;
+
+       pid = forkpty(&master, line, NULL, &win);
+       if (pid < 0) {
+               if (errno == ENOENT)
+                       fatal(f, "Out of ptys", 0);
+               else
+                       fatal(f, "Forkpty", 1);
+       }
+       if (pid == 0) {
+               if (f > 2)      /* f should always be 0, but... */
+                       (void) close(f);
+               setup_term(0);
+               if (authenticated) {
+#ifdef KERBEROS
+                       if (use_kerberos && (pwd->pw_uid == 0))
+                               syslog(LOG_INFO|LOG_AUTH,
+                                   "ROOT Kerberos login from %s.%s@%s on %s\n",
+                                   kdata->pname, kdata->pinst, kdata->prealm,
+                                   hostname);
+#endif
+
+                       execle(_PATH_LOGIN, "login", "-p",
+                           "-h", hostname, "-f", "--", lusername, NULL, env);
+               } else
+                       execle(_PATH_LOGIN, "login", "-p",
+                           "-h", hostname, "--", lusername, NULL, env);
+               fatal(STDERR_FILENO, _PATH_LOGIN, 1);
+               /*NOTREACHED*/
+       }
+#ifdef CRYPT
+#ifdef KERBEROS
+       /*
+        * If encrypted, don't turn on NBIO or the des read/write
+        * routines will croak.
+        */
+
+       if (!doencrypt)
+#endif
+#endif
+               ioctl(f, FIONBIO, &on);
+       ioctl(master, FIONBIO, &on);
+       ioctl(master, TIOCPKT, &on);
+       signal(SIGCHLD, cleanup);
+       protocol(f, master);
+       signal(SIGCHLD, SIG_IGN);
+       cleanup(0);
+}
+
+char   magic[2] = { 0377, 0377 };
+char   oobdata[] = {TIOCPKT_WINDOW};
+
+/*
+ * Handle a "control" request (signaled by magic being present)
+ * in the data stream.  For now, we are only willing to handle
+ * window size changes.
+ */
+int
+control(pty, cp, n)
+       int pty;
+       char *cp;
+       int n;
+{
+       struct winsize w;
+
+       if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
+               return (0);
+       oobdata[0] &= ~TIOCPKT_WINDOW;  /* we know he heard */
+       memmove(&w, cp+4, sizeof(w));
+       w.ws_row = ntohs(w.ws_row);
+       w.ws_col = ntohs(w.ws_col);
+       w.ws_xpixel = ntohs(w.ws_xpixel);
+       w.ws_ypixel = ntohs(w.ws_ypixel);
+       (void)ioctl(pty, TIOCSWINSZ, &w);
+       return (4+sizeof (w));
+}
+
+/*
+ * rlogin "protocol" machine.
+ */
+void
+protocol(f, p)
+       register int f, p;
+{
+       char pibuf[1024+1], fibuf[1024], *pbp, *fbp;
+       register pcc = 0, fcc = 0;
+       int cc, nfd, n;
+       char cntl;
+
+       /*
+        * Must ignore SIGTTOU, otherwise we'll stop
+        * when we try and set slave pty's window shape
+        * (our controlling tty is the master pty).
+        */
+       (void) signal(SIGTTOU, SIG_IGN);
+       send(f, oobdata, 1, MSG_OOB);   /* indicate new rlogin */
+       if (f > p)
+               nfd = f + 1;
+       else
+               nfd = p + 1;
+       if (nfd > FD_SETSIZE) {
+               syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE");
+               fatal(f, "internal error (select mask too small)", 0);
+       }
+       for (;;) {
+               fd_set ibits, obits, ebits, *omask;
+
+               FD_ZERO(&ebits);
+               FD_ZERO(&ibits);
+               FD_ZERO(&obits);
+               omask = (fd_set *)NULL;
+               if (fcc) {
+                       FD_SET(p, &obits);
+                       omask = &obits;
+               } else
+                       FD_SET(f, &ibits);
+               if (pcc >= 0)
+                       if (pcc) {
+                               FD_SET(f, &obits);
+                               omask = &obits;
+                       } else
+                               FD_SET(p, &ibits);
+               FD_SET(p, &ebits);
+               if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       fatal(f, "select", 1);
+               }
+               if (n == 0) {
+                       /* shouldn't happen... */
+                       sleep(5);
+                       continue;
+               }
+#define        pkcontrol(c)    ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
+               if (FD_ISSET(p, &ebits)) {
+                       cc = read(p, &cntl, 1);
+                       if (cc == 1 && pkcontrol(cntl)) {
+                               cntl |= oobdata[0];
+                               send(f, &cntl, 1, MSG_OOB);
+                               if (cntl & TIOCPKT_FLUSHWRITE) {
+                                       pcc = 0;
+                                       FD_CLR(p, &ibits);
+                               }
+                       }
+               }
+               if (FD_ISSET(f, &ibits)) {
+#ifdef CRYPT
+#ifdef KERBEROS
+                       if (doencrypt)
+                               fcc = des_read(f, fibuf, sizeof(fibuf));
+                       else
+#endif
+#endif
+                               fcc = read(f, fibuf, sizeof(fibuf));
+                       if (fcc < 0 && errno == EWOULDBLOCK)
+                               fcc = 0;
+                       else {
+                               register char *cp;
+                               int left, n;
+
+                               if (fcc <= 0)
+                                       break;
+                               fbp = fibuf;
+
+                       top:
+                               for (cp = fibuf; cp < fibuf+fcc-1; cp++)
+                                       if (cp[0] == magic[0] &&
+                                           cp[1] == magic[1]) {
+                                               left = fcc - (cp-fibuf);
+                                               n = control(p, cp, left);
+                                               if (n) {
+                                                       left -= n;
+                                                       if (left > 0)
+                                                               bcopy(cp+n, cp, left);
+                                                       fcc -= n;
+                                                       goto top; /* n^2 */
+                                               }
+                                       }
+                               FD_SET(p, &obits);              /* try write */
+                       }
+               }
+
+               if (FD_ISSET(p, &obits) && fcc > 0) {
+                       cc = write(p, fbp, fcc);
+                       if (cc > 0) {
+                               fcc -= cc;
+                               fbp += cc;
+                       }
+               }
+
+               if (FD_ISSET(p, &ibits)) {
+                       pcc = read(p, pibuf, sizeof (pibuf));
+                       pbp = pibuf;
+                       if (pcc < 0 && errno == EWOULDBLOCK)
+                               pcc = 0;
+                       else if (pcc <= 0)
+                               break;
+                       else if (pibuf[0] == 0) {
+                               pbp++, pcc--;
+#ifdef CRYPT
+#ifdef KERBEROS
+                               if (!doencrypt)
+#endif
+#endif
+                                       FD_SET(f, &obits);      /* try write */
+                       } else {
+                               if (pkcontrol(pibuf[0])) {
+                                       pibuf[0] |= oobdata[0];
+                                       send(f, &pibuf[0], 1, MSG_OOB);
+                               }
+                               pcc = 0;
+                       }
+               }
+               if ((FD_ISSET(f, &obits)) && pcc > 0) {
+#ifdef CRYPT
+#ifdef KERBEROS
+                       if (doencrypt)
+                               cc = des_write(f, pbp, pcc);
+                       else
+#endif
+#endif
+                               cc = write(f, pbp, pcc);
+                       if (cc < 0 && errno == EWOULDBLOCK) {
+                               /*
+                                * This happens when we try write after read
+                                * from p, but some old kernels balk at large
+                                * writes even when select returns true.
+                                */
+                               if (!FD_ISSET(p, &ibits))
+                                       sleep(5);
+                               continue;
+                       }
+                       if (cc > 0) {
+                               pcc -= cc;
+                               pbp += cc;
+                       }
+               }
+       }
+}
+
+void
+cleanup(signo)
+       int signo;
+{
+       char *p;
+
+       p = line + sizeof(_PATH_DEV) - 1;
+       if (logout(p))
+               logwtmp(p, "", "");
+       (void)chmod(line, 0666);
+       (void)chown(line, 0, 0);
+       *p = 'p';
+       (void)chmod(line, 0666);
+       (void)chown(line, 0, 0);
+       shutdown(netf, 2);
+       exit(1);
+}
+
+void
+fatal(f, msg, syserr)
+       int f;
+       char *msg;
+       int syserr;
+{
+       int len;
+       char buf[BUFSIZ], *bp = buf;
+
+       /*
+        * Prepend binary one to message if we haven't sent
+        * the magic null as confirmation.
+        */
+       if (!confirmed)
+               *bp++ = '\01';          /* error indicator */
+       if (syserr)
+               len = sprintf(bp, "rlogind: %s: %s.\r\n",
+                   msg, strerror(errno));
+       else
+               len = sprintf(bp, "rlogind: %s.\r\n", msg);
+       (void) write(f, buf, bp + len - buf);
+       exit(1);
+}
+
+int
+do_rlogin(dest)
+       struct sockaddr_in *dest;
+{
+       getstr(rusername, sizeof(rusername), "remuser too long");
+       getstr(lusername, sizeof(lusername), "locuser too long");
+       getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
+
+       pwd = getpwnam(lusername);
+       if (pwd == NULL)
+               return (-1);
+       if (pwd->pw_uid == 0)
+               return (-1);
+       /* XXX why don't we syslog() failure? */
+       return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername));
+}
+
+void
+getstr(buf, cnt, errmsg)
+       char *buf;
+       int cnt;
+       char *errmsg;
+{
+       char c;
+
+       do {
+               if (read(0, &c, 1) != 1)
+                       exit(1);
+               if (--cnt < 0)
+                       fatal(STDOUT_FILENO, errmsg, 0);
+               *buf++ = c;
+       } while (c != 0);
+}
+
+void
+setup_term(fd)
+       int fd;
+{
+       register char *cp = index(term+ENVSIZE, '/');
+       char *speed;
+       struct termios tt;
+
+#ifndef notyet
+       tcgetattr(fd, &tt);
+       if (cp) {
+               *cp++ = '\0';
+               speed = cp;
+               cp = index(speed, '/');
+               if (cp)
+                       *cp++ = '\0';
+               cfsetspeed(&tt, atoi(speed));
+       }
+
+       tt.c_iflag = TTYDEF_IFLAG;
+       tt.c_oflag = TTYDEF_OFLAG;
+       tt.c_lflag = TTYDEF_LFLAG;
+       tcsetattr(fd, TCSAFLUSH, &tt);
+#else
+       if (cp) {
+               *cp++ = '\0';
+               speed = cp;
+               cp = index(speed, '/');
+               if (cp)
+                       *cp++ = '\0';
+               tcgetattr(fd, &tt);
+               cfsetspeed(&tt, atoi(speed));
+               tcsetattr(fd, TCSAFLUSH, &tt);
+       }
+#endif
+
+       env[0] = term;
+       env[1] = 0;
+}
+
+#ifdef KERBEROS
+#define        VERSION_SIZE    9
+
+/*
+ * Do the remote kerberos login to the named host with the
+ * given inet address
+ *
+ * Return 0 on valid authorization
+ * Return -1 on valid authentication, no authorization
+ * Return >0 for error conditions
+ */
+int
+do_krb_login(dest)
+       struct sockaddr_in *dest;
+{
+       int rc;
+       char instance[INST_SZ], version[VERSION_SIZE];
+       long authopts = 0L;     /* !mutual */
+       struct sockaddr_in faddr;
+
+       kdata = (AUTH_DAT *) auth_buf;
+       ticket = (KTEXT) tick_buf;
+
+       instance[0] = '*';
+       instance[1] = '\0';
+
+#ifdef CRYPT
+       if (doencrypt) {
+               rc = sizeof(faddr);
+               if (getsockname(0, (struct sockaddr *)&faddr, &rc))
+                       return (-1);
+               authopts = KOPT_DO_MUTUAL;
+               rc = krb_recvauth(
+                       authopts, 0,
+                       ticket, "rcmd",
+                       instance, dest, &faddr,
+                       kdata, "", schedule, version);
+                des_set_key(kdata->session, schedule);
+
+       } else
+#endif
+               rc = krb_recvauth(
+                       authopts, 0,
+                       ticket, "rcmd",
+                       instance, dest, (struct sockaddr_in *) 0,
+                       kdata, "", (bit_64 *) 0, version);
+
+       if (rc != KSUCCESS)
+               return (rc);
+
+       getstr(lusername, sizeof(lusername), "locuser");
+       /* get the "cmd" in the rcmd protocol */
+       getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
+
+       pwd = getpwnam(lusername);
+       if (pwd == NULL)
+               return (-1);
+
+       /* returns nonzero for no access */
+       if (kuserok(kdata, lusername) != 0)
+               return (-1);
+       
+       return (0);
+
+}
+#endif /* KERBEROS */
+
+void
+usage()
+{
+#ifdef KERBEROS
+       syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]");
+#else
+       syslog(LOG_ERR, "usage: rlogind [-aln]");
+#endif
+}
+
+/*
+ * Check whether host h is in our local domain,
+ * defined as sharing the last two components of the domain part,
+ * or the entire domain part if the local domain has only one component.
+ * If either name is unqualified (contains no '.'),
+ * assume that the host is local, as it will be
+ * interpreted as such.
+ */
+int
+local_domain(h)
+       char *h;
+{
+       char localhost[MAXHOSTNAMELEN];
+       char *p1, *p2;
+
+       localhost[0] = 0;
+       (void) gethostname(localhost, sizeof(localhost));
+       p1 = topdomain(localhost);
+       p2 = topdomain(h);
+       if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
+               return (1);
+       return (0);
+}
+
+char *
+topdomain(h)
+       char *h;
+{
+       register char *p;
+       char *maybe = NULL;
+       int dots = 0;
+
+       for (p = h + strlen(h); p >= h; p--) {
+               if (*p == '.') {
+                       if (++dots == 2)
+                               return (p);
+                       maybe = p;
+               }
+       }
+       return (maybe);
+}
diff --git a/route.tproj/Makefile b/route.tproj/Makefile
new file mode 100644 (file)
index 0000000..d1a9e0e
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = route
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = keywords.h
+
+CFILES = ccitt_addr.c route.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            route.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/route.tproj/Makefile.dist b/route.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..f7de878
--- /dev/null
@@ -0,0 +1,25 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  route
+MAN8=  route.0
+SRCS=  route.c ccitt_addr.c
+CFLAGS+=-I.
+CLEANFILES+=keywords.h
+BINOWN=        root
+BINMODE=4555
+
+all: route ${MAN8}
+
+keywords.h: keywords
+       sed -e '/^#/d' -e '/^$$/d' ${.CURDIR}/keywords > _keywords.tmp
+       tr a-z A-Z < _keywords.tmp | paste _keywords.tmp - | \
+           awk '{ \
+               if (NF > 1) \
+                       printf "#define\tK_%s\t%d\n\t{\"%s\", K_%s},\n", \
+                           $$2, NR, $$1, $$2 }' \
+           > ${.TARGET}
+       rm -f _keywords.tmp
+
+.include <bsd.prog.mk>
+
+route .depend lint tags: keywords.h
diff --git a/route.tproj/Makefile.postamble b/route.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..670967c
--- /dev/null
@@ -0,0 +1 @@
+INSTALL_PERMISSIONS = 4555    # If set, 'install' chmod's executable to this
diff --git a/route.tproj/Makefile.preamble b/route.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/route.tproj/PB.project b/route.tproj/PB.project
new file mode 100644 (file)
index 0000000..f27333b
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        CLASSES = (); 
+        FRAMEWORKS = (); 
+        H_FILES = (keywords.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (ccitt_addr.c, route.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, route.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = route; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_MAINNIB = route; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = route; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_MAINNIB = route; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/route.tproj/ccitt_addr.c b/route.tproj/ccitt_addr.c
new file mode 100644 (file)
index 0000000..9c57be3
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ccitt_addr.c        8.2 (Berkeley) 4/28/95
+ */
+
+/*
+ * parse CCITT addresses
+ *
+ * Addresses must have the format: [hpr],x121address[,userdata][,protocol]
+ * items enclosed with square brackets are optional
+ * 'h' or 'p' means hi priority (packet size = 128; specific to Datapac
+ * and necessary only for X.25(76) and non-negotiating X.25(80) DTE's)
+ * 'r' means reverse charge (remote DTE pays for call).
+ * The x121address consists of an optional netid and dot, followed
+ * by a dte address.
+ *
+ * Frank Pronk
+ * The University of British Columbia
+ * Laboratory for Computational Vision
+ * Copyright (c) 1984
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <bsd/netccitt/x25.h>
+
+static char *copychar ();
+
+ccitt_addr (addr, xp)
+char *addr;
+register struct sockaddr_x25 *xp;
+{
+       register char *p, *ap, *limit;
+       int havenet = 0;
+
+       memset(xp, 0, sizeof (*xp));
+       xp->x25_family = AF_CCITT;
+       xp->x25_len = sizeof(*xp);
+       p = addr;
+
+       /*
+        * process optional priority and reverse charging flags
+        */
+
+       if (*p == 'p' || *p == 'r' || *p == 'h') {
+               while (*p == 'p' || *p == 'r' || *p == 'h') {
+                       if (*p == 'p' || *p == 'h')
+                               xp->x25_opts.op_psize = X25_PS128;
+                       else if (*p == 'r')
+                               xp->x25_opts.op_flags |= X25_REVERSE_CHARGE;
+                       p++;
+               }
+               if (*p != ',')
+                       return (0);
+               p++;
+       }
+       if (*p == '\0')
+               return (0);
+
+       /*
+        * [network id:]X.121 address
+        */
+
+       ap = xp->x25_addr;
+       limit = ap + sizeof (xp->x25_addr) - 1;
+       while (*p) {
+               if (*p == ',')
+                       break;
+               if (*p == '.' || *p == ':') {
+                       if (havenet)
+                               return (0);
+                       havenet++;
+                       xp->x25_net = atoi (xp->x25_addr);
+                       p++;
+                       ap = xp->x25_addr;
+                       *ap = '\0';
+               }
+               if (*p < '0' || *p > '9')
+                       return (0);
+               if (ap >= limit)
+                       return (0);
+               *ap++ = *p++;
+       }
+       if (*p == '\0')
+               return (1);
+
+       /*
+        * optional user data, bytes 4 to 16
+        */
+
+       p++;
+       ap = xp->x25_udata + 4;         /* first four bytes are protocol id */
+       limit = ap + sizeof (xp->x25_udata) - 4;
+       xp->x25_udlen = 4;
+       while (*p) {
+               if (*p == ',')
+                       break;
+               if (ap >= limit)
+                       return (0);
+               p = copychar (p, ap++);
+               xp->x25_udlen++;
+       }
+       if (xp->x25_udlen == 4)
+               xp->x25_udlen = 0;
+       if (*p == '\0')
+               return (1);
+
+       p++;
+       ap = xp->x25_udata;             /* protocol id */
+       limit = ap + (xp->x25_udlen ? 4 : sizeof(xp->x25_udata));
+       while (*p) {
+               if (*p == ',')
+                       return (0);
+               if (ap >= limit)
+                       return (0);
+               p = copychar (p, ap++);
+       }
+       if (xp->x25_udlen == 0)
+               xp->x25_udlen = ap - xp->x25_udata;
+       return (1);
+}
+
+static char *
+copychar (from, to)
+register char *from, *to;
+{
+       register int n;
+
+       if (*from != '\\' || from[1] < '0' || from[1] > '7') {
+               *to = *from++;
+               return (from);
+       }
+       n = *++from - '0';
+       from++;
+       if (*from >= '0' && *from <= '7') {
+               register int n1;
+
+               n = n*8 + *from++ - '0';
+               if (*from >= '0' && *from <= '7' && (n1 = n*8 + *from-'0') < 256) {
+                       n = n1;
+                       from++;
+               }
+       }
+       *to = n;
+       return (from);
+}
diff --git a/route.tproj/keywords.h b/route.tproj/keywords.h
new file mode 100644 (file)
index 0000000..bb5eebd
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#define        K_ADD   1
+       {"add", K_ADD},
+#define        K_BLACKHOLE     2
+       {"blackhole", K_BLACKHOLE},
+#define        K_CHANGE        3
+       {"change", K_CHANGE},
+#define        K_CLONING       4
+       {"cloning", K_CLONING},
+#define        K_DELETE        5
+       {"delete", K_DELETE},
+#define        K_DST   6
+       {"dst", K_DST},
+#define        K_EXPIRE        7
+       {"expire", K_EXPIRE},
+#define        K_FLUSH 8
+       {"flush", K_FLUSH},
+#define        K_GATEWAY       9
+       {"gateway", K_GATEWAY},
+#define        K_GENMASK       10
+       {"genmask", K_GENMASK},
+#define        K_GET   11
+       {"get", K_GET},
+#define        K_HOST  12
+       {"host", K_HOST},
+#define        K_HOPCOUNT      13
+       {"hopcount", K_HOPCOUNT},
+#define        K_IFACE 14
+       {"iface", K_IFACE},
+#define        K_INTERFACE     15
+       {"interface", K_INTERFACE},
+#define        K_IFA   16
+       {"ifa", K_IFA},
+#define        K_IFP   17
+       {"ifp", K_IFP},
+#define        K_INET  18
+       {"inet", K_INET},
+#define        K_ISO   19
+       {"iso", K_ISO},
+#define        K_LINK  20
+       {"link", K_LINK},
+#define        K_LOCK  21
+       {"lock", K_LOCK},
+#define        K_LOCKREST      22
+       {"lockrest", K_LOCKREST},
+#define        K_MASK  23
+       {"mask", K_MASK},
+#define        K_MONITOR       24
+       {"monitor", K_MONITOR},
+#define        K_MTU   25
+       {"mtu", K_MTU},
+#define        K_NET   26
+       {"net", K_NET},
+#define        K_NETMASK       27
+       {"netmask", K_NETMASK},
+#define        K_NOSTATIC      28
+       {"nostatic", K_NOSTATIC},
+#define        K_OSI   29
+       {"osi", K_OSI},
+#define        K_PROTO1        30
+       {"proto1", K_PROTO1},
+#define        K_PROTO2        31
+       {"proto2", K_PROTO2},
+#define        K_RECVPIPE      32
+       {"recvpipe", K_RECVPIPE},
+#define        K_REJECT        33
+       {"reject", K_REJECT},
+#define        K_RTT   34
+       {"rtt", K_RTT},
+#define        K_RTTVAR        35
+       {"rttvar", K_RTTVAR},
+#define        K_SA    36
+       {"sa", K_SA},
+#define        K_SENDPIPE      37
+       {"sendpipe", K_SENDPIPE},
+#define        K_SSTHRESH      38
+       {"ssthresh", K_SSTHRESH},
+#define        K_STATIC        39
+       {"static", K_STATIC},
+#define        K_X25   40
+       {"x25", K_X25},
+#define        K_XNS   41
+       {"xns", K_XNS},
+#define        K_XRESOLVE      42
+       {"xresolve", K_XRESOLVE},
+#define K_LLINFO       43
+       {"llinfo", K_LLINFO},
diff --git a/route.tproj/route.8 b/route.tproj/route.8
new file mode 100644 (file)
index 0000000..62b9cfe
--- /dev/null
@@ -0,0 +1,325 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)route.8    8.4 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt ROUTE 8
+.Os BSD 4.4
+.Sh NAME
+.Nm route
+.Nd manually manipulate the routing tables.
+.Sh SYNOPSIS
+.Nm route
+.Op Fl nqv
+.Ar command
+.Oo
+.Op Ar modifiers
+.Ar args
+.Oc
+.Sh DESCRIPTION
+.Nm Route
+is a utility used to manually manipulate the network
+routing tables.  It normally is not needed, as a
+system routing table management daemon such as
+.Xr routed 8 ,
+should tend to this task.
+.Pp
+The
+.Nm route :
+utility supports a limited number of general options,
+but a rich command language, enabling the user to specify
+any arbitrary request that could be delivered via the
+programmatic interface discussed in 
+.Xr route 4 .
+.Pp
+.Bl -tag -width Ds
+.It Fl n
+Bypasses attempts to print host and network names symbolically
+when reporting actions.  (The process of translating between symbolic
+names and numerical equivalents can be quite time consuming, and
+may require correct operation of the network; thus it may be expedient
+to forgo this, especially when attempting to repair networking operations),
+.It Fl v
+(verbose) Print additional details.
+.It Fl q
+Suppress all output.
+.El
+.Pp
+The
+.Nm route :
+utility provides six commands:
+.Pp
+.Bl -tag -width Fl -compact
+.It Cm add
+Add a route.
+.It Cm flush
+Remove all routes.
+.It Cm delete
+Delete a specific route.
+.It Cm change
+Change aspects of a route (such as its gateway).
+.It Cm get
+Lookup and display the route for a destination.
+.It Cm monitor
+Continuously report any changes to the routing information base,
+routing lookup misses, or suspected network partitionings.
+.El
+.Pp
+The monitor command has the syntax
+.Pp
+.Bd -filled -offset indent -compact
+.Nm route Op Fl n
+.Cm monitor
+.Ed
+.Pp
+The flush command has the syntax
+.Pp
+.Bd -filled -offset indent -compact
+.Nm route Op Fl n
+.Cm flush
+.Op Ar family
+.Ed
+.Pp
+If the 
+.Cm flush
+command is specified, 
+.Nm route
+will ``flush'' the routing tables of all gateway entries.
+When the address family may is specified by any of the
+.Fl osi ,
+.Fl xns ,
+or
+.Fl inet
+modifiers, only routes having destinations with addresses in the
+delineated family will be deleted.
+.Pp
+The other commands have the following syntax:
+.Pp
+.Bd -filled -offset indent -compact
+.Nm route Op Fl n
+.Ar command
+.Op Fl net No \&| Fl host
+.Ar destination gateway
+.Ed
+.Pp
+where
+.Ar destination
+is the destination host or network,
+.Ar gateway
+is the next-hop intermediary via which packets should be routed.
+Routes to a particular host may be distinguished from those to
+a network by interpreting the Internet address specified as the
+.Ar destination argument.
+The optional modifiers
+.Fl net
+and
+.Fl host
+force the destination to be interpreted as a network or a host, respectively.
+Otherwise, if the 
+.Ar destination
+has a ``local address part'' of
+INADDR_ANY ,
+or if the
+.Ar destination
+is the symbolic name of a network, then the route is
+assumed to be to a network; otherwise, it is presumed to be a
+route to a host.
+.Pp
+For example,
+.Li 128.32
+is interpreted as
+.Fl host Li 128.0.0.32 ;
+.Li 128.32.130
+is interpreted as
+.Fl host Li 128.32.0.130 ;
+.Fl net Li 128.32
+is interpreted as
+.Li 128.32.0.0;
+and 
+.Fl net Li 128.32.130
+is interpreted as
+.Li 128.32.130.0 .
+.Pp
+If the destination is directly reachable
+via an interface requiring
+no intermediary system to act as a gateway, the 
+.Fl interface
+modifier should be specified;
+the gateway given is the address of this host on the common network,
+indicating the interface to be used for transmission.
+.Pp
+The optional modifiers
+.Fl xns ,
+.Fl osi ,
+and
+.Fl link 
+specify that all subsequent addresses are in the
+.Tn XNS
+.Tn OSI
+address families,
+or are specified as link-level addresses,
+and the names must be numeric specifications rather than
+symbolic names.
+.Pp
+The optional
+.Fl netmask
+qualifier is intended
+to achieve the effect of an
+.Tn OSI
+.Tn ESIS
+redirect with the netmask option,
+or to manually add subnet routes with
+netmasks different from that of the implied network interface
+(as would otherwise be communicated using the OSPF or ISIS routing protocols).
+One specifies an additional ensuing address parameter
+(to be interpreted as a network mask).
+The implicit network mask generated in the AF_INET case
+can be overridden by making sure this option follows the destination parameter.
+.Pp
+Routes have associated flags which influence operation of the protocols
+when sending to destinations matched by the routes.
+These flags may be set (or sometimes cleared)
+by indicating the following corresponding modifiers:
+.Bd -literal
+-cloning   RTF_CLONING    - generates a new route on use
+-xresolve  RTF_XRESOLVE   - emit mesg on use (for external lookup)
+-iface    ~RTF_GATEWAY    - destination is directly reachable
+-static    RTF_STATIC     - manually added route
+-nostatic ~RTF_STATIC     - pretend route added by kernel or daemon
+-reject    RTF_REJECT     - emit an ICMP unreachable when matched
+-blackhole RTF_BLACKHOLE  - silently discard pkts (during updates)
+-proto1    RTF_PROTO1     - set protocol specific routing flag #1
+-proto2    RTF_PROTO2     - set protocol specific routing flag #2
+-llinfo    RTF_LLINFO     - validly translates proto addr to link addr
+.Ed
+.Pp
+The optional modifiers
+.Fl rtt ,
+.Fl rttvar ,
+.Fl sendpipe ,
+.Fl recvpipe ,
+.Fl mtu ,
+.Fl hopcount ,
+.Fl expire ,
+and
+.Fl ssthresh
+provide initial values to quantities maintained in the routing entry
+by transport level protocols, such as TCP or TP4.
+These may be individually locked by preceding each such modifier to
+be locked by
+the
+.Fl lock
+meta-modifier, or one can 
+specify that all ensuing metrics may be locked by the
+.Fl lockrest
+meta-modifier.
+.Pp
+In a
+.Cm change
+or
+.Cm add
+command where the destination and gateway are not sufficient to specify
+the route (as in the
+.Tn ISO
+case where several interfaces may have the
+same address), the
+.Fl ifp
+or
+.Fl ifa
+modifiers may be used to determine the interface or interface address.
+.Pp
+All symbolic names specified for a
+.Ar destination
+or 
+.Ar gateway
+are looked up first as a host name using
+.Xr gethostbyname 3 .
+If this lookup fails,
+.Xr getnetbyname 3
+is then used to interpret the name as that of a network.
+.Pp
+.Nm Route
+uses a routing socket and the new message types
+RTM_ADD,
+RTM_DELETE,
+RTM_GET,
+and
+RTM_CHANGE.
+As such, only the super-user may modify
+the routing tables.
+.ne 1i
+.Sh DIAGNOSTICS
+.Bl -tag -width Ds
+.It Sy "add [host \&| network ] %s: gateway %s flags %x"
+The specified route is being added to the tables.  The
+values printed are from the routing table entry supplied
+in the 
+.Xr ioctl 2
+call.
+If the gateway address used was not the primary address of the gateway
+(the first one returned by
+.Xr gethostbyname 3 ) ,
+the gateway address is printed numerically as well as symbolically.
+.It Sy "delete [ host &| network ] %s: gateway %s flags %x" 
+As above, but when deleting an entry.
+.It Sy "%s %s done"
+When the 
+.Cm flush
+command is specified, each routing table entry deleted
+is indicated with a message of this form.
+.It Sy "Network is unreachable"
+An attempt to add a route failed because the gateway listed was not
+on a directly-connected network.
+The next-hop gateway must be given.
+.It Sy "not in table"
+A delete operation was attempted for an entry which
+wasn't present in the tables.
+.It Sy "routing table overflow"
+An add operation was attempted, but the system was
+low on resources and was unable to allocate memory
+to create the new entry.
+.El
+.Sh SEE ALSO
+.Xr netintro 4 ,
+.Xr route 4 ,
+.Xr esis 4 ,
+.Xr routed 8 ,
+.Xr XNSrouted 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+The first paragraph may have slightly exaggerated
+.Xr routed Ns 's
+abilities.
diff --git a/route.tproj/route.c b/route.tproj/route.c
new file mode 100644 (file)
index 0000000..9c53a27
--- /dev/null
@@ -0,0 +1,1523 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1989, 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1983, 1989, 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)route.c    8.3 (Berkeley) 3/19/94";
+#endif
+static const char rcsid[] =
+       "$Id: route.c,v 1.1.1.2 2000/01/11 01:49:18 wsanchez Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#ifdef AT
+#include <netatalk/at.h>
+#endif
+#ifdef NS
+#include <netns/ns.h>
+#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+struct keytab {
+       char    *kt_cp;
+       int     kt_i;
+} keywords[] = {
+#include "keywords.h"
+       {0, 0}
+};
+
+struct ortentry route;
+union  sockunion {
+       struct  sockaddr sa;
+       struct  sockaddr_in sin;
+#ifdef AT
+       struct  sockaddr_at sat;
+#endif
+#ifdef NS
+       struct  sockaddr_ns sns;
+#endif
+       struct  sockaddr_dl sdl;
+} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
+
+typedef union sockunion *sup;
+int    pid, rtm_addrs, uid;
+int    s;
+int    forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword();
+int    iflag, verbose, aflen = sizeof (struct sockaddr_in);
+int    locking, lockrest, debugonly;
+struct rt_metrics rt_metrics;
+u_long  rtm_inits;
+struct in_addr inet_makeaddr();
+#ifdef AT
+int    atalk_aton __P((const char *, struct at_addr *));
+char   *atalk_ntoa __P((struct at_addr));
+#endif
+char   *routename(), *netname();
+void   flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
+void   print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
+int    getaddr(), rtmsg(), x25_makemask();
+extern char *inet_ntoa(), *iso_ntoa(), *link_ntoa();
+
+void usage __P((const char *));
+
+void
+usage(cp)
+       const char *cp;
+{
+       if (cp)
+               warnx("bad keyword: %s", cp);
+       (void) fprintf(stderr,
+           "usage: route [-dnqtv] command [[modifiers] args]\n");
+       exit(EX_USAGE);
+       /* NOTREACHED */
+}
+
+#define ROUNDUP(a) \
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       int ch;
+
+       if (argc < 2)
+               usage((char *)NULL);
+
+       while ((ch = getopt(argc, argv, "nqdtv")) != -1)
+               switch(ch) {
+               case 'n':
+                       nflag = 1;
+                       break;
+               case 'q':
+                       qflag = 1;
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 't':
+                       tflag = 1;
+                       break;
+               case 'd':
+                       debugonly = 1;
+                       break;
+               case '?':
+               default:
+                       usage((char *)NULL);
+               }
+       argc -= optind;
+       argv += optind;
+
+       pid = getpid();
+       uid = getuid();
+       if (tflag)
+               s = open("/dev/null", O_WRONLY, 0);
+       else
+               s = socket(PF_ROUTE, SOCK_RAW, 0);
+       if (s < 0)
+               err(EX_OSERR, "socket");
+       setuid(uid);
+       if (*argv)
+               switch (keyword(*argv)) {
+               case K_GET:
+                       uid = 0;
+                       /* FALLTHROUGH */
+
+               case K_CHANGE:
+               case K_ADD:
+               case K_DELETE:
+                       newroute(argc, argv);
+                       exit(0);
+                       /* NOTREACHED */
+
+               case K_MONITOR:
+                       monitor();
+                       /* NOTREACHED */
+
+               case K_FLUSH:
+                       flushroutes(argc, argv);
+                       exit(0);
+                       /* NOTREACHED */
+               }
+       usage(*argv);
+       /* NOTREACHED */
+}
+
+/*
+ * Purge all entries in the routing tables not
+ * associated with network interfaces.
+ */
+void
+flushroutes(argc, argv)
+       int argc;
+       char *argv[];
+{
+       size_t needed;
+       int mib[6], rlen, seqno;
+       char *buf, *next, *lim;
+       register struct rt_msghdr *rtm;
+
+       if (uid) {
+               errx(EX_NOPERM, "must be root to alter routing table");
+       }
+       shutdown(s, 0); /* Don't want to read back our messages */
+       if (argc > 1) {
+               argv++;
+               if (argc == 2 && **argv == '-')
+                   switch (keyword(*argv + 1)) {
+                       case K_INET:
+                               af = AF_INET;
+                               break;
+
+#ifdef
+                       case K_ATALK:
+                               af = AF_APPLETALK;
+                               break;
+#endif
+#ifdef NS
+                       case K_XNS:
+                               af = AF_NS;
+                               break;
+#endif
+                       case K_LINK:
+                               af = AF_LINK;
+                               break;
+                       default:
+                               goto bad;
+               } else
+bad:                   usage(*argv);
+       }
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;             /* protocol */
+       mib[3] = 0;             /* wildcard address family */
+       mib[4] = NET_RT_DUMP;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+               err(EX_OSERR, "route-sysctl-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               errx(EX_OSERR, "malloc failed");
+       if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+               err(EX_OSERR, "route-sysctl-get");
+       lim = buf + needed;
+       if (verbose)
+               (void) printf("Examining routing table from sysctl\n");
+       seqno = 0;              /* ??? */
+       for (next = buf; next < lim; next += rtm->rtm_msglen) {
+               rtm = (struct rt_msghdr *)next;
+               if (verbose)
+                       print_rtmsg(rtm, rtm->rtm_msglen);
+               if ((rtm->rtm_flags & RTF_GATEWAY) == 0)
+                       continue;
+               if (af) {
+                       struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+
+                       if (sa->sa_family != af)
+                               continue;
+               }
+               if (debugonly)
+                       continue;
+               rtm->rtm_type = RTM_DELETE;
+               rtm->rtm_seq = seqno;
+               rlen = write(s, next, rtm->rtm_msglen);
+               if (rlen < (int)rtm->rtm_msglen) {
+                       warn("write to routing socket");
+                       (void) printf("got only %d for rlen\n", rlen);
+                       break;
+               }
+               seqno++;
+               if (qflag)
+                       continue;
+               if (verbose)
+                       print_rtmsg(rtm, rlen);
+               else {
+                       struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+                       (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
+                           routename(sa) : netname(sa));
+                       sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
+                       (void) printf("%-20.20s ", routename(sa));
+                       (void) printf("done\n");
+               }
+       }
+}
+
+char *
+routename(sa)
+       struct sockaddr *sa;
+{
+       register char *cp;
+       static char line[MAXHOSTNAMELEN + 1];
+       struct hostent *hp;
+       static char domain[MAXHOSTNAMELEN + 1];
+       static int first = 1;
+#ifdef NS
+       char *ns_print();
+#endif
+
+       if (first) {
+               first = 0;
+               if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+                   (cp = index(domain, '.'))) {
+                       domain[MAXHOSTNAMELEN] = '\0';
+                       (void) strcpy(domain, cp + 1);
+               } else
+                       domain[0] = 0;
+       }
+
+       if (sa->sa_len == 0)
+               strcpy(line, "default");
+       else switch (sa->sa_family) {
+
+       case AF_INET:
+           {   struct in_addr in;
+               in = ((struct sockaddr_in *)sa)->sin_addr;
+
+               cp = 0;
+               if (in.s_addr == INADDR_ANY || sa->sa_len < 4)
+                       cp = "default";
+               if (cp == 0 && !nflag) {
+                       hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
+                               AF_INET);
+                       if (hp) {
+                               if ((cp = index(hp->h_name, '.')) &&
+                                   !strcmp(cp + 1, domain))
+                                       *cp = 0;
+                               cp = hp->h_name;
+                       }
+               }
+               if (cp) {
+                       strncpy(line, cp, sizeof(line) - 1);
+                       line[sizeof(line) - 1] = '\0';
+               } else {
+                       /* XXX - why not inet_ntoa()? */
+#define C(x)   (unsigned)((x) & 0xff)
+                       in.s_addr = ntohl(in.s_addr);
+                       (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+                          C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
+               }
+               break;
+           }
+#ifdef AT
+       case AF_APPLETALK:
+               (void) snprintf(line, sizeof(line), "atalk %s",
+                       atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
+               break;
+#endif
+#ifdef NS
+       case AF_NS:
+               return (ns_print((struct sockaddr_ns *)sa));
+#endif
+
+       case AF_LINK:
+               return (link_ntoa((struct sockaddr_dl *)sa));
+
+       default:
+           {   u_short *s = (u_short *)sa;
+               u_short *slim = s + ((sa->sa_len + 1) >> 1);
+               char *cp = line + sprintf(line, "(%d)", sa->sa_family);
+               char *cpe = line + sizeof(line);
+
+               while (++s < slim && cp < cpe) /* start with sa->sa_data */
+                       cp += snprintf(cp, cpe - cp, " %x", *s);
+               break;
+           }
+       }
+       return (line);
+}
+
+/*
+ * Return the name of the network whose address is given.
+ * The address is assumed to be that of a net or subnet, not a host.
+ */
+char *
+netname(sa)
+       struct sockaddr *sa;
+{
+       char *cp = 0;
+       static char line[MAXHOSTNAMELEN + 1];
+       struct netent *np = 0;
+       u_long net, mask;
+       register u_long i;
+       int subnetshift;
+#ifdef NS
+       char *ns_print();
+#endif
+
+       switch (sa->sa_family) {
+
+       case AF_INET:
+           {   struct in_addr in;
+               in = ((struct sockaddr_in *)sa)->sin_addr;
+
+               i = in.s_addr = ntohl(in.s_addr);
+               if (in.s_addr == 0)
+                       cp = "default";
+               else if (!nflag) {
+                       if (IN_CLASSA(i)) {
+                               mask = IN_CLASSA_NET;
+                               subnetshift = 8;
+                       } else if (IN_CLASSB(i)) {
+                               mask = IN_CLASSB_NET;
+                               subnetshift = 8;
+                       } else {
+                               mask = IN_CLASSC_NET;
+                               subnetshift = 4;
+                       }
+                       /*
+                        * If there are more bits than the standard mask
+                        * would suggest, subnets must be in use.
+                        * Guess at the subnet mask, assuming reasonable
+                        * width subnet fields.
+                        */
+                       while (in.s_addr &~ mask)
+                               mask = (long)mask >> subnetshift;
+                       net = in.s_addr & mask;
+                       while ((mask & 1) == 0)
+                               mask >>= 1, net >>= 1;
+                       np = getnetbyaddr(net, AF_INET);
+                       if (np)
+                               cp = np->n_name;
+               }
+               if (cp)
+                       strncpy(line, cp, sizeof(line));
+               else if ((in.s_addr & 0xffffff) == 0)
+                       (void) sprintf(line, "%u", C(in.s_addr >> 24));
+               else if ((in.s_addr & 0xffff) == 0)
+                       (void) sprintf(line, "%u.%u", C(in.s_addr >> 24),
+                           C(in.s_addr >> 16));
+               else if ((in.s_addr & 0xff) == 0)
+                       (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
+                           C(in.s_addr >> 16), C(in.s_addr >> 8));
+               else
+                       (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+                           C(in.s_addr >> 16), C(in.s_addr >> 8),
+                           C(in.s_addr));
+               break;
+           }
+#ifdef AT
+       case AF_APPLETALK:
+               (void) snprintf(line, sizeof(line), "atalk %s",
+                       atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
+               break;
+#endif
+#ifdef NS
+       case AF_NS:
+               return (ns_print((struct sockaddr_ns *)sa));
+               break;
+#endif
+
+       case AF_LINK:
+               return (link_ntoa((struct sockaddr_dl *)sa));
+
+
+       default:
+           {   u_short *s = (u_short *)sa->sa_data;
+               u_short *slim = s + ((sa->sa_len + 1)>>1);
+               char *cp = line + sprintf(line, "af %d:", sa->sa_family);
+               char *cpe = line + sizeof(line);
+
+               while (s < slim && cp < cpe)
+                       cp += snprintf(cp, cpe - cp, " %x", *s++);
+               break;
+           }
+       }
+       return (line);
+}
+
+void
+set_metric(value, key)
+       char *value;
+       int key;
+{
+       int flag = 0;
+       u_long noval, *valp = &noval;
+
+       switch (key) {
+#define caseof(x, y, z)        case x: valp = &rt_metrics.z; flag = y; break
+       caseof(K_MTU, RTV_MTU, rmx_mtu);
+       caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount);
+       caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire);
+       caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe);
+       caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe);
+       caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh);
+       caseof(K_RTT, RTV_RTT, rmx_rtt);
+       caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar);
+       }
+       rtm_inits |= flag;
+       if (lockrest || locking)
+               rt_metrics.rmx_locks |= flag;
+       if (locking)
+               locking = 0;
+       *valp = atoi(value);
+}
+
+void
+newroute(argc, argv)
+       int argc;
+       register char **argv;
+{
+       char *cmd, *dest = "", *gateway = "", *err;
+       int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC;
+       int key;
+       struct hostent *hp = 0;
+
+       if (uid) {
+               errx(EX_NOPERM, "must be root to alter routing table");
+       }
+       cmd = argv[0];
+       if (*cmd != 'g')
+               shutdown(s, 0); /* Don't want to read back our messages */
+       while (--argc > 0) {
+               if (**(++argv)== '-') {
+                       switch (key = keyword(1 + *argv)) {
+                       case K_LINK:
+                               af = AF_LINK;
+                               aflen = sizeof(struct sockaddr_dl);
+                               break;
+                       case K_INET:
+                               af = AF_INET;
+                               aflen = sizeof(struct sockaddr_in);
+                               break;
+#ifdef AT
+                       case K_ATALK:
+                               af = AF_APPLETALK;
+                               aflen = sizeof(struct sockaddr_at);
+                               break;
+#endif
+                       case K_SA:
+                               af = PF_ROUTE;
+                               aflen = sizeof(union sockunion);
+                               break;
+#ifdef NS
+                       case K_XNS:
+                               af = AF_NS;
+                               aflen = sizeof(struct sockaddr_ns);
+                               break;
+#endif
+                       case K_IFACE:
+                       case K_INTERFACE:
+                               iflag++;
+                               break;
+                       case K_NOSTATIC:
+                               flags &= ~RTF_STATIC;
+                               break;
+
+                       case K_LLINFO:
+                               flags |= RTF_LLINFO;
+                               break;
+
+                       case K_LOCK:
+                               locking = 1;
+                               break;
+                       case K_LOCKREST:
+                               lockrest = 1;
+                               break;
+                       case K_HOST:
+                               forcehost++;
+                               break;
+                       case K_REJECT:
+                               flags |= RTF_REJECT;
+                               break;
+                       case K_BLACKHOLE:
+                               flags |= RTF_BLACKHOLE;
+                               break;
+                       case K_PROTO1:
+                               flags |= RTF_PROTO1;
+                               break;
+                       case K_PROTO2:
+                               flags |= RTF_PROTO2;
+                               break;
+                       case K_CLONING:
+                               flags |= RTF_CLONING;
+                               break;
+                       case K_XRESOLVE:
+                               flags |= RTF_XRESOLVE;
+                               break;
+                       case K_STATIC:
+                               flags |= RTF_STATIC;
+                               break;
+                       case K_IFA:
+                               argc--;
+                               (void) getaddr(RTA_IFA, *++argv, 0);
+                               break;
+                       case K_IFP:
+                               argc--;
+                               (void) getaddr(RTA_IFP, *++argv, 0);
+                               break;
+                       case K_GENMASK:
+                               argc--;
+                               (void) getaddr(RTA_GENMASK, *++argv, 0);
+                               break;
+                       case K_GATEWAY:
+                               argc--;
+                               (void) getaddr(RTA_GATEWAY, *++argv, 0);
+                               break;
+                       case K_DST:
+                               argc--;
+                               ishost = getaddr(RTA_DST, *++argv, &hp);
+                               dest = *argv;
+                               break;
+                       case K_NETMASK:
+                               argc--;
+                               (void) getaddr(RTA_NETMASK, *++argv, 0);
+                               /* FALLTHROUGH */
+                       case K_NET:
+                               forcenet++;
+                               break;
+                       case K_MTU:
+                       case K_HOPCOUNT:
+                       case K_EXPIRE:
+                       case K_RECVPIPE:
+                       case K_SENDPIPE:
+                       case K_SSTHRESH:
+                       case K_RTT:
+                       case K_RTTVAR:
+                               argc--;
+                               set_metric(*++argv, key);
+                               break;
+                       default:
+                               usage(1+*argv);
+                       }
+               } else {
+                       if ((rtm_addrs & RTA_DST) == 0) {
+                               dest = *argv;
+                               ishost = getaddr(RTA_DST, *argv, &hp);
+                       } else if ((rtm_addrs & RTA_GATEWAY) == 0) {
+                               gateway = *argv;
+                               (void) getaddr(RTA_GATEWAY, *argv, &hp);
+                       } else {
+                               (void) getaddr(RTA_NETMASK, *argv, 0);
+                       }
+               }
+       }
+       if (forcehost)
+               ishost = 1;
+       if (forcenet)
+               ishost = 0;
+       flags |= RTF_UP;
+       if (ishost)
+               flags |= RTF_HOST;
+       if (iflag == 0)
+               flags |= RTF_GATEWAY;
+       for (attempts = 1; ; attempts++) {
+               errno = 0;
+               if ((ret = rtmsg(*cmd, flags)) == 0)
+                       break;
+               if (errno != ENETUNREACH && errno != ESRCH)
+                       break;
+               if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) {
+                       hp->h_addr_list++;
+                       bcopy(hp->h_addr_list[0], &so_gate.sin.sin_addr,
+                           MIN(hp->h_length, sizeof(so_gate.sin.sin_addr)));
+               } else
+                       break;
+       }
+       if (*cmd == 'g')
+               exit(0);
+       oerrno = errno;
+       (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest);
+       if (*gateway) {
+               (void) printf(": gateway %s", gateway);
+               if (attempts > 1 && ret == 0 && af == AF_INET)
+                   (void) printf(" (%s)",
+                       inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
+       }
+       if (ret == 0)
+               (void) printf("\n");
+       else {
+               switch (oerrno) {
+               case ESRCH:
+                       err = "not in table";
+                       break;
+               case EBUSY:
+                       err = "entry in use";
+                       break;
+               case ENOBUFS:
+                       err = "routing table overflow";
+                       break;
+               default:
+                       err = strerror(oerrno);
+                       break;
+               }
+               (void) printf(": %s\n", err);
+       }
+}
+
+void
+inet_makenetandmask(net, sin, bits)
+       u_long net, bits;
+       register struct sockaddr_in *sin;
+{
+       u_long addr, mask = 0;
+       register char *cp;
+
+       rtm_addrs |= RTA_NETMASK;
+       if (net == 0)
+               mask = addr = 0;
+       else if (bits) {
+               addr = net;
+               mask = 0xffffffff << (32 - bits);
+       } else if (net < 128) {
+               addr = net << IN_CLASSA_NSHIFT;
+               mask = IN_CLASSA_NET;
+       } else if (net < 65536) {
+               addr = net << IN_CLASSB_NSHIFT;
+               mask = IN_CLASSB_NET;
+       } else if (net < 16777216L) {
+               addr = net << IN_CLASSC_NSHIFT;
+               mask = IN_CLASSC_NET;
+       } else {
+               addr = net;
+               if ((addr & IN_CLASSA_HOST) == 0)
+                       mask =  IN_CLASSA_NET;
+               else if ((addr & IN_CLASSB_HOST) == 0)
+                       mask =  IN_CLASSB_NET;
+               else if ((addr & IN_CLASSC_HOST) == 0)
+                       mask =  IN_CLASSC_NET;
+               else
+                       mask = -1;
+       }
+       sin->sin_addr.s_addr = htonl(addr);
+       sin = &so_mask.sin;
+       sin->sin_addr.s_addr = htonl(mask);
+       sin->sin_len = 0;
+       sin->sin_family = 0;
+       cp = (char *)(&sin->sin_addr + 1);
+       while (*--cp == 0 && cp > (char *)sin)
+               ;
+       sin->sin_len = 1 + cp - (char *)sin;
+}
+
+/*
+ * Interpret an argument as a network address of some kind,
+ * returning 1 if a host address, 0 if a network address.
+ */
+int
+getaddr(which, s, hpp)
+       int which;
+       char *s;
+       struct hostent **hpp;
+{
+       register sup su;
+#ifdef NS
+       struct ns_addr ns_addr();
+#endif
+       struct hostent *hp;
+       struct netent *np;
+       u_long val;
+       char *q,qs;
+
+       if (af == 0) {
+               af = AF_INET;
+               aflen = sizeof(struct sockaddr_in);
+       }
+       rtm_addrs |= which;
+       switch (which) {
+       case RTA_DST:
+               su = &so_dst;
+               break;
+       case RTA_GATEWAY:
+               su = &so_gate;
+               if (iflag) {
+                       #define MAX_IFACES      400
+                       int                     sock;
+                       struct ifreq            iflist[MAX_IFACES];
+                       struct ifconf           ifconf;
+                       struct ifreq            *ifr, *ifr_end;
+                       struct sockaddr_dl      *dl, *sdl = NULL;
+
+                       /* Get socket */
+                       if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
+                               err(1, "socket");
+
+                       /* Get interface list */
+                       ifconf.ifc_req = iflist;
+                       ifconf.ifc_len = sizeof(iflist);
+                       if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0)
+                               err(1, "ioctl(SIOCGIFCONF)");
+                       close(sock);
+
+                       /* Look for this interface in the list */
+                       for (ifr = ifconf.ifc_req,
+                           ifr_end = (struct ifreq *)
+                               (ifconf.ifc_buf + ifconf.ifc_len);
+                           ifr < ifr_end;
+                           ifr = (struct ifreq *) ((char *) &ifr->ifr_addr
+                                                   + ifr->ifr_addr.sa_len)) {
+                               dl = (struct sockaddr_dl *)&ifr->ifr_addr;
+                               if (ifr->ifr_addr.sa_family == AF_LINK
+                                   && (ifr->ifr_flags & IFF_POINTOPOINT)
+                                   && !strncmp(s, dl->sdl_data, dl->sdl_nlen)
+                                   && s[dl->sdl_nlen] == 0) {
+                                       sdl = dl;
+                                       break;
+                               }
+                       }
+
+                       /* If we found it, then use it */
+                       if (sdl) {
+                               su->sdl = *sdl;
+                               return(1);
+                       }
+               }
+               break;
+       case RTA_NETMASK:
+               su = &so_mask;
+               break;
+       case RTA_GENMASK:
+               su = &so_genmask;
+               break;
+       case RTA_IFP:
+               su = &so_ifp;
+               break;
+       case RTA_IFA:
+               su = &so_ifa;
+               break;
+       default:
+               usage("internal error");
+               /*NOTREACHED*/
+       }
+       su->sa.sa_len = aflen;
+       su->sa.sa_family = af; /* cases that don't want it have left already */
+       if (strcmp(s, "default") == 0) {
+               /*
+                * Default is net 0.0.0.0/0 
+                */
+               switch (which) {
+               case RTA_DST:
+                       forcenet++;
+                       /* bzero(su, sizeof(*su)); *//* for readability */
+                       (void) getaddr(RTA_NETMASK, s, 0);
+                       break;
+#if 0
+               case RTA_NETMASK:
+               case RTA_GENMASK:
+                       /* bzero(su, sizeof(*su)); *//* for readability */
+#endif
+               }
+               return (0);
+       }
+       switch (af) {
+#ifdef NS
+       case AF_NS:
+               if (which == RTA_DST) {
+                       extern short ns_bh[3];
+                       struct sockaddr_ns *sms = &(so_mask.sns);
+                       bzero((char *)sms, sizeof(*sms));
+                       sms->sns_family = 0;
+                       sms->sns_len = 6;
+                       sms->sns_addr.x_net = *(union ns_net *)ns_bh;
+                       rtm_addrs |= RTA_NETMASK;
+               }
+               su->sns.sns_addr = ns_addr(s);
+               return (!ns_nullhost(su->sns.sns_addr));
+#endif
+
+#ifdef AT
+       case AF_APPLETALK:
+               if (!atalk_aton(s, &su->sat.sat_addr))
+                       errx(EX_NOHOST, "bad address: %s", s);
+               rtm_addrs |= RTA_NETMASK;
+               return(forcehost || su->sat.sat_addr.s_node != 0);
+#endif
+       case AF_LINK:
+               link_addr(s, &su->sdl);
+               return (1);
+
+
+       case PF_ROUTE:
+               su->sa.sa_len = sizeof(*su);
+               sockaddr(s, &su->sa);
+               return (1);
+
+       case AF_INET:
+       default:
+               break;
+       }
+
+       if (hpp == NULL)
+               hpp = &hp;
+       *hpp = NULL;
+
+       q = strchr(s,'/');
+       if (q && which == RTA_DST) {
+               qs = *q;
+               *q = '\0';
+               if (((val = inet_addr(s)) != INADDR_NONE)) {
+                       inet_makenetandmask(
+                               htonl(val), &su->sin, strtoul(q+1, 0, 0));
+                       return (0);
+               }
+               *q =qs;
+       }
+       if (((val = inet_addr(s)) != INADDR_NONE) &&
+           (which != RTA_DST || forcenet == 0)) {
+               su->sin.sin_addr.s_addr = val;
+               if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
+                       return (1);
+               else {
+                       val = ntohl(val);
+                       goto netdone;
+               }
+       }
+       if ((val = inet_network(s)) != INADDR_NONE ||
+           (forcehost == 0 && (np = getnetbyname(s)) != NULL &&
+                   (val = np->n_net) != 0)) {
+netdone:
+               if (which == RTA_DST)
+                       inet_makenetandmask(val, &su->sin, 0);
+               return (0);
+       }
+       hp = gethostbyname(s);
+       if (hp) {
+               *hpp = hp;
+               su->sin.sin_family = hp->h_addrtype;
+               bcopy(hp->h_addr, (char *)&su->sin.sin_addr, 
+                   MIN(hp->h_length, sizeof(su->sin.sin_addr)));
+               return (1);
+       }
+       errx(EX_NOHOST, "bad address: %s", s);
+}
+
+
+#ifdef NS
+short ns_nullh[] = {0,0,0};
+short ns_bh[] = {-1,-1,-1};
+
+char *
+ns_print(sns)
+       struct sockaddr_ns *sns;
+{
+       struct ns_addr work;
+       union { union ns_net net_e; u_long long_e; } net;
+       u_short port;
+       static char mybuf[50+MAXHOSTNAMELEN], cport[10], chost[25];
+       char *host = "";
+       register char *p;
+       register u_char *q;
+
+       work = sns->sns_addr;
+       port = ntohs(work.x_port);
+       work.x_port = 0;
+       net.net_e  = work.x_net;
+       if (ns_nullhost(work) && net.long_e == 0) {
+               if (!port)
+                       return ("*.*");
+               (void) sprintf(mybuf, "*.%XH", port);
+               return (mybuf);
+       }
+
+       if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0)
+               host = "any";
+       else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0)
+               host = "*";
+       else {
+               q = work.x_host.c_host;
+               (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH",
+                       q[0], q[1], q[2], q[3], q[4], q[5]);
+               for (p = chost; *p == '0' && p < chost + 12; p++)
+                       /* void */;
+               host = p;
+       }
+       if (port)
+               (void) sprintf(cport, ".%XH", htons(port));
+       else
+               *cport = 0;
+
+       (void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s", 
+                    (unsigned long)ntohl(net.long_e),
+                      host, cport);
+       return (mybuf);
+}
+#endif
+
+void
+interfaces()
+{
+       size_t needed;
+       int mib[6];
+       char *buf, *lim, *next;
+       register struct rt_msghdr *rtm;
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;             /* protocol */
+       mib[3] = 0;             /* wildcard address family */
+       mib[4] = NET_RT_IFLIST;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+               err(EX_OSERR, "route-sysctl-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               errx(EX_OSERR, "malloc failed");
+       if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+               err(EX_OSERR, "actual retrieval of interface table");
+       lim = buf + needed;
+       for (next = buf; next < lim; next += rtm->rtm_msglen) {
+               rtm = (struct rt_msghdr *)next;
+               print_rtmsg(rtm, rtm->rtm_msglen);
+       }
+}
+
+void
+monitor()
+{
+       int n;
+       char msg[2048];
+
+       verbose = 1;
+       if (debugonly) {
+               interfaces();
+               exit(0);
+       }
+       for(;;) {
+               n = read(s, msg, 2048);
+               (void) printf("got message of size %d\n", n);
+               print_rtmsg((struct rt_msghdr *)msg, n);
+       }
+}
+
+struct {
+       struct  rt_msghdr m_rtm;
+       char    m_space[512];
+} m_rtmsg;
+
+int
+rtmsg(cmd, flags)
+       int cmd, flags;
+{
+       static int seq;
+       int rlen;
+       register char *cp = m_rtmsg.m_space;
+       register int l;
+
+#define NEXTADDR(w, u) \
+       if (rtm_addrs & (w)) {\
+           l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
+           if (verbose) sodump(&(u),"u");\
+       }
+
+       errno = 0;
+       bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
+       if (cmd == 'a')
+               cmd = RTM_ADD;
+       else if (cmd == 'c')
+               cmd = RTM_CHANGE;
+       else if (cmd == 'g') {
+               cmd = RTM_GET;
+               if (so_ifp.sa.sa_family == 0) {
+                       so_ifp.sa.sa_family = AF_LINK;
+                       so_ifp.sa.sa_len = sizeof(struct sockaddr_dl);
+                       rtm_addrs |= RTA_IFP;
+               }
+       } else
+               cmd = RTM_DELETE;
+#define rtm m_rtmsg.m_rtm
+       rtm.rtm_type = cmd;
+       rtm.rtm_flags = flags;
+       rtm.rtm_version = RTM_VERSION;
+       rtm.rtm_seq = ++seq;
+       rtm.rtm_addrs = rtm_addrs;
+       rtm.rtm_rmx = rt_metrics;
+       rtm.rtm_inits = rtm_inits;
+
+       if (rtm_addrs & RTA_NETMASK)
+               mask_addr();
+       NEXTADDR(RTA_DST, so_dst);
+       NEXTADDR(RTA_GATEWAY, so_gate);
+       NEXTADDR(RTA_NETMASK, so_mask);
+       NEXTADDR(RTA_GENMASK, so_genmask);
+       NEXTADDR(RTA_IFP, so_ifp);
+       NEXTADDR(RTA_IFA, so_ifa);
+       rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
+       if (verbose)
+               print_rtmsg(&rtm, l);
+       if (debugonly)
+               return (0);
+       if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
+               warn("writing to routing socket");
+               return (-1);
+       }
+       if (cmd == RTM_GET) {
+               do {
+                       l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+               } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
+               if (l < 0)
+                       warn("read from routing socket");
+               else
+                       print_getmsg(&rtm, l);
+       }
+#undef rtm
+       return (0);
+}
+
+void
+mask_addr()
+{
+       int olen = so_mask.sa.sa_len;
+       register char *cp1 = olen + (char *)&so_mask, *cp2;
+
+       for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; )
+               if (*--cp1 != 0) {
+                       so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask;
+                       break;
+               }
+       if ((rtm_addrs & RTA_DST) == 0)
+               return;
+       switch (so_dst.sa.sa_family) {
+#ifdef NS
+       case AF_NS:
+#endif
+       case AF_INET:
+       case AF_APPLETALK:
+       case 0:
+               return;
+       }
+       cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst;
+       cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst;
+       while (cp2 > cp1)
+               *--cp2 = 0;
+       cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask;
+       while (cp1 > so_dst.sa.sa_data)
+               *--cp1 &= *--cp2;
+}
+
+char *msgtypes[] = {
+       "",
+       "RTM_ADD: Add Route",
+       "RTM_DELETE: Delete Route",
+       "RTM_CHANGE: Change Metrics or flags",
+       "RTM_GET: Report Metrics",
+       "RTM_LOSING: Kernel Suspects Partitioning",
+       "RTM_REDIRECT: Told to use different route",
+       "RTM_MISS: Lookup failed on this address",
+       "RTM_LOCK: fix specified metrics",
+       "RTM_OLDADD: caused by SIOCADDRT",
+       "RTM_OLDDEL: caused by SIOCDELRT",
+       "RTM_RESOLVE: Route created by cloning",
+       "RTM_NEWADDR: address being added to iface",
+       "RTM_DELADDR: address being removed from iface",
+       "RTM_IFINFO: iface status change",
+       "RTM_NEWMADDR: new multicast group membership on iface",
+       "RTM_DELMADDR: multicast group membership removed from iface",
+       0,
+};
+
+char metricnames[] =
+"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount"
+"\1mtu";
+char routeflags[] =
+"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT"
+"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016"
+"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024CHAINDELETE"
+"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST";
+char ifnetflags[] =
+"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
+"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
+"\017LINK2\020MULTICAST";
+char addrnames[] =
+"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
+
+void
+print_rtmsg(rtm, msglen)
+       register struct rt_msghdr *rtm;
+       int msglen;
+{
+       struct if_msghdr *ifm;
+       struct ifa_msghdr *ifam;
+#ifdef RTM_NEWMADDR
+       struct ifma_msghdr *ifmam;
+#endif
+
+       if (verbose == 0)
+               return;
+       if (rtm->rtm_version != RTM_VERSION) {
+               (void) printf("routing message version %d not understood\n",
+                   rtm->rtm_version);
+               return;
+       }
+       (void)printf("%s: len %d, ", msgtypes[rtm->rtm_type], rtm->rtm_msglen);
+       switch (rtm->rtm_type) {
+       case RTM_IFINFO:
+               ifm = (struct if_msghdr *)rtm;
+               (void) printf("if# %d, flags:", ifm->ifm_index);
+               bprintf(stdout, ifm->ifm_flags, ifnetflags);
+               pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs);
+               break;
+       case RTM_NEWADDR:
+       case RTM_DELADDR:
+               ifam = (struct ifa_msghdr *)rtm;
+               (void) printf("metric %d, flags:", ifam->ifam_metric);
+               bprintf(stdout, ifam->ifam_flags, routeflags);
+               pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs);
+               break;
+#ifdef RTM_NEWMADDR
+       case RTM_NEWMADDR:
+       case RTM_DELMADDR:
+               ifmam = (struct ifma_msghdr *)rtm;
+               pmsg_addrs((char *)(ifmam + 1), ifmam->ifmam_addrs);
+               break;
+#endif
+       default:
+               (void) printf("pid: %ld, seq %d, errno %d, flags:",
+                       (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
+               bprintf(stdout, rtm->rtm_flags, routeflags);
+               pmsg_common(rtm);
+       }
+}
+
+void
+print_getmsg(rtm, msglen)
+       register struct rt_msghdr *rtm;
+       int msglen;
+{
+       struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
+       struct sockaddr_dl *ifp = NULL;
+       register struct sockaddr *sa;
+       register char *cp;
+       register int i;
+
+       (void) printf("   route to: %s\n", routename(&so_dst));
+       if (rtm->rtm_version != RTM_VERSION) {
+               warnx("routing message version %d not understood",
+                    rtm->rtm_version);
+               return;
+       }
+       if (rtm->rtm_msglen > msglen) {
+               warnx("message length mismatch, in packet %d, returned %d",
+                     rtm->rtm_msglen, msglen);
+       }
+       if (rtm->rtm_errno)  {
+               errno = rtm->rtm_errno;
+               warn("message indicates error %d", errno);
+               return;
+       }
+       cp = ((char *)(rtm + 1));
+       if (rtm->rtm_addrs)
+               for (i = 1; i; i <<= 1)
+                       if (i & rtm->rtm_addrs) {
+                               sa = (struct sockaddr *)cp;
+                               switch (i) {
+                               case RTA_DST:
+                                       dst = sa;
+                                       break;
+                               case RTA_GATEWAY:
+                                       gate = sa;
+                                       break;
+                               case RTA_NETMASK:
+                                       mask = sa;
+                                       break;
+                               case RTA_IFP:
+                                       if (sa->sa_family == AF_LINK &&
+                                          ((struct sockaddr_dl *)sa)->sdl_nlen)
+                                               ifp = (struct sockaddr_dl *)sa;
+                                       break;
+                               }
+                               ADVANCE(cp, sa);
+                       }
+       if (dst && mask)
+               mask->sa_family = dst->sa_family;       /* XXX */
+       if (dst)
+               (void)printf("destination: %s\n", routename(dst));
+       if (mask) {
+               int savenflag = nflag;
+
+               nflag = 1;
+               (void)printf("       mask: %s\n", routename(mask));
+               nflag = savenflag;
+       }
+       if (gate && rtm->rtm_flags & RTF_GATEWAY)
+               (void)printf("    gateway: %s\n", routename(gate));
+       if (ifp)
+               (void)printf("  interface: %.*s\n",
+                   ifp->sdl_nlen, ifp->sdl_data);
+       (void)printf("      flags: ");
+       bprintf(stdout, rtm->rtm_flags, routeflags);
+
+#define lock(f)        ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ')
+#define msec(u)        (((u) + 500) / 1000)            /* usec to msec */
+
+       (void) printf("\n%s\n", "\
+ recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire");
+       printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
+       printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
+       printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
+       printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
+       printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
+       printf("%8ld%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
+       printf("%8ld%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
+       if (rtm->rtm_rmx.rmx_expire)
+               rtm->rtm_rmx.rmx_expire -= time(0);
+       printf("%8ld%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
+#undef lock
+#undef msec
+#define        RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
+       if (verbose)
+               pmsg_common(rtm);
+       else if (rtm->rtm_addrs &~ RTA_IGN) {
+               (void) printf("sockaddrs: ");
+               bprintf(stdout, rtm->rtm_addrs, addrnames);
+               putchar('\n');
+       }
+#undef RTA_IGN
+}
+
+void
+pmsg_common(rtm)
+       register struct rt_msghdr *rtm;
+{
+       (void) printf("\nlocks: ");
+       bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
+       (void) printf(" inits: ");
+       bprintf(stdout, rtm->rtm_inits, metricnames);
+       pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs);
+}
+
+void
+pmsg_addrs(cp, addrs)
+       char    *cp;
+       int     addrs;
+{
+       register struct sockaddr *sa;
+       int i;
+
+       if (addrs == 0)
+               return;
+       (void) printf("\nsockaddrs: ");
+       bprintf(stdout, addrs, addrnames);
+       (void) putchar('\n');
+       for (i = 1; i; i <<= 1)
+               if (i & addrs) {
+                       sa = (struct sockaddr *)cp;
+                       (void) printf(" %s", routename(sa));
+                       ADVANCE(cp, sa);
+               }
+       (void) putchar('\n');
+       (void) fflush(stdout);
+}
+
+void
+bprintf(fp, b, s)
+       register FILE *fp;
+       register int b;
+       register u_char *s;
+{
+       register int i;
+       int gotsome = 0;
+
+       if (b == 0)
+               return;
+       while ((i = *s++) != 0) {
+               if (b & (1 << (i-1))) {
+                       if (gotsome == 0)
+                               i = '<';
+                       else
+                               i = ',';
+                       (void) putc(i, fp);
+                       gotsome = 1;
+                       for (; (i = *s) > 32; s++)
+                               (void) putc(i, fp);
+               } else
+                       while (*s > 32)
+                               s++;
+       }
+       if (gotsome)
+               (void) putc('>', fp);
+}
+
+int
+keyword(cp)
+       char *cp;
+{
+       register struct keytab *kt = keywords;
+
+       while (kt->kt_cp && strcmp(kt->kt_cp, cp))
+               kt++;
+       return kt->kt_i;
+}
+
+void
+sodump(su, which)
+       register sup su;
+       char *which;
+{
+       switch (su->sa.sa_family) {
+       case AF_LINK:
+               (void) printf("%s: link %s; ",
+                   which, link_ntoa(&su->sdl));
+               break;
+       case AF_INET:
+               (void) printf("%s: inet %s; ",
+                   which, inet_ntoa(su->sin.sin_addr));
+               break;
+#ifdef AT
+       case AF_APPLETALK:
+               (void) printf("%s: atalk %s; ",
+                   which, atalk_ntoa(su->sat.sat_addr));
+               break;
+#endif
+#ifdef NS
+       case AF_NS:
+               (void) printf("%s: xns %s; ",
+                   which, ns_ntoa(su->sns.sns_addr));
+               break;
+#endif
+       }
+       (void) fflush(stdout);
+}
+
+/* States*/
+#define VIRGIN 0
+#define GOTONE 1
+#define GOTTWO 2
+/* Inputs */
+#define        DIGIT   (4*0)
+#define        END     (4*1)
+#define DELIM  (4*2)
+
+void
+sockaddr(addr, sa)
+       register char *addr;
+       register struct sockaddr *sa;
+{
+       register char *cp = (char *)sa;
+       int size = sa->sa_len;
+       char *cplim = cp + size;
+       register int byte = 0, state = VIRGIN, new = 0 /* foil gcc */;
+
+       bzero(cp, size);
+       cp++;
+       do {
+               if ((*addr >= '0') && (*addr <= '9')) {
+                       new = *addr - '0';
+               } else if ((*addr >= 'a') && (*addr <= 'f')) {
+                       new = *addr - 'a' + 10;
+               } else if ((*addr >= 'A') && (*addr <= 'F')) {
+                       new = *addr - 'A' + 10;
+               } else if (*addr == 0)
+                       state |= END;
+               else
+                       state |= DELIM;
+               addr++;
+               switch (state /* | INPUT */) {
+               case GOTTWO | DIGIT:
+                       *cp++ = byte; /*FALLTHROUGH*/
+               case VIRGIN | DIGIT:
+                       state = GOTONE; byte = new; continue;
+               case GOTONE | DIGIT:
+                       state = GOTTWO; byte = new + (byte << 4); continue;
+               default: /* | DELIM */
+                       state = VIRGIN; *cp++ = byte; byte = 0; continue;
+               case GOTONE | END:
+               case GOTTWO | END:
+                       *cp++ = byte; /* FALLTHROUGH */
+               case VIRGIN | END:
+                       break;
+               }
+               break;
+       } while (cp < cplim);
+       sa->sa_len = cp - (char *)sa;
+}
+
+#ifdef AT
+int
+atalk_aton(const char *text, struct at_addr *addr)
+{
+       u_int net, node;
+
+       if (sscanf(text, "%u.%u", &net, &node) != 2
+           || net > 0xffff || node > 0xff)
+               return(0);
+       addr->s_net = htons(net);
+       addr->s_node = node;
+       return(1);
+}
+
+char *
+atalk_ntoa(struct at_addr at)
+{
+       static char buf[20];
+
+       (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node);
+       return(buf);
+}
+#endif
diff --git a/routed.tproj/Makefile b/routed.tproj/Makefile
new file mode 100644 (file)
index 0000000..78e1951
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = routed
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = af.h defs.h interface.h pathnames.h table.h trace.h
+
+CFILES = af.c defs.c if.c inet.c input.c main.c output.c startup.c\
+         tables.c timer.c trace.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist routed.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/routed.tproj/Makefile.dist b/routed.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..d9dd7f8
--- /dev/null
@@ -0,0 +1,22 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/19/93
+
+PROG=  routed
+SRCS=  af.c if.c input.c main.c output.c startup.c tables.c timer.c \
+       trace.c inet.c
+MAN8=  routed.0
+#SUBDIR=       query trace
+DPADD= ${LIBCOMPAT}
+LDADD= -lcompat
+
+.include <bsd.prog.mk>
+
+.if (${MACHINE} == "vax")
+# The following can be deleted where not appropriate to use the kernel's
+# inline code expansions.
+INLINE=        /sys/vax/inline/obj/inline
+C2=    /usr/libexec/c2
+.c.o:
+       ${CC} -S ${CFLAGS} ${.CURDIR}/${.PREFIX}.c
+       @${C2} ${.PREFIX}.s | ${INLINE} | ${AS} -o ${.PREFIX}.o
+       @rm -f ${.PREFIX}.s
+.endif
diff --git a/routed.tproj/Makefile.preamble b/routed.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/routed.tproj/PB.project b/routed.tproj/PB.project
new file mode 100644 (file)
index 0000000..23f9195
--- /dev/null
@@ -0,0 +1,53 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (af.h, defs.h, interface.h, pathnames.h, table.h, trace.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (
+            af.c, 
+            defs.c, 
+            if.c, 
+            inet.c, 
+            input.c, 
+            main.c, 
+            output.c, 
+            startup.c, 
+            tables.c, 
+            timer.c, 
+            trace.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, routed.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_MAINNIB = routed; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_MAINNIB = routed; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = routed; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_MAINNIB = routed; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/routed.tproj/af.c b/routed.tproj/af.c
new file mode 100644 (file)
index 0000000..a879b6c
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+#include "defs.h"
+
+/*
+ * Address family support routines
+ */
+int    inet_hash(), inet_netmatch(), inet_output(),
+       inet_portmatch(), inet_portcheck(),
+       inet_checkhost(), inet_rtflags(), inet_sendroute(), inet_canon();
+char   *inet_format();
+
+#define NIL    { 0 }
+#define        INET \
+       { inet_hash,            inet_netmatch,          inet_output, \
+         inet_portmatch,       inet_portcheck,         inet_checkhost, \
+         inet_rtflags,         inet_sendroute,         inet_canon, \
+         inet_format \
+       }
+
+struct afswitch afswitch[AF_MAX] = {
+       NIL,            /* 0- unused */
+       NIL,            /* 1- Unix domain, unused */
+       INET,           /* Internet */
+};
+
+int af_max = sizeof(afswitch) / sizeof(afswitch[0]);
+
+struct sockaddr_in inet_default = {
+#ifdef RTM_ADD
+       sizeof (inet_default),
+#endif
+       AF_INET, INADDR_ANY };
+
+inet_hash(sin, hp)
+       register struct sockaddr_in *sin;
+       struct afhash *hp;
+{
+       register u_long n;
+
+       n = inet_netof(sin->sin_addr);
+       if (n)
+           while ((n & 0xff) == 0)
+               n >>= 8;
+       hp->afh_nethash = n;
+       hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
+       hp->afh_hosthash &= 0x7fffffff;
+}
+
+inet_netmatch(sin1, sin2)
+       struct sockaddr_in *sin1, *sin2;
+{
+
+       return (inet_netof(sin1->sin_addr) == inet_netof(sin2->sin_addr));
+}
+
+/*
+ * Verify the message is from the right port.
+ */
+inet_portmatch(sin)
+       register struct sockaddr_in *sin;
+{
+       
+       return (sin->sin_port == sp->s_port);
+}
+
+/*
+ * Verify the message is from a "trusted" port.
+ */
+inet_portcheck(sin)
+       struct sockaddr_in *sin;
+{
+
+       return (ntohs(sin->sin_port) <= IPPORT_RESERVED);
+}
+
+/*
+ * Internet output routine.
+ */
+inet_output(s, flags, sin, size)
+       int s, flags;
+       struct sockaddr_in *sin;
+       int size;
+{
+       struct sockaddr_in dst;
+
+       dst = *sin;
+       sin = &dst;
+       if (sin->sin_port == 0)
+               sin->sin_port = sp->s_port;
+       if (sin->sin_len == 0)
+               sin->sin_len = sizeof (*sin);
+       if (sendto(s, packet, size, flags,
+           (struct sockaddr *)sin, sizeof (*sin)) < 0)
+               perror("sendto");
+}
+
+/*
+ * Return 1 if the address is believed
+ * for an Internet host -- THIS IS A KLUDGE.
+ */
+inet_checkhost(sin)
+       struct sockaddr_in *sin;
+{
+       u_long i = ntohl(sin->sin_addr.s_addr);
+
+#ifndef IN_EXPERIMENTAL
+#define        IN_EXPERIMENTAL(i)      (((long) (i) & 0xe0000000) == 0xe0000000)
+#endif
+
+       if (IN_EXPERIMENTAL(i) || sin->sin_port != 0)
+               return (0);
+       if (i != 0 && (i & 0xff000000) == 0)
+               return (0);
+       for (i = 0; i < sizeof(sin->sin_zero)/sizeof(sin->sin_zero[0]); i++)
+               if (sin->sin_zero[i])
+                       return (0);
+       return (1);
+}
+
+inet_canon(sin)
+       struct sockaddr_in *sin;
+{
+
+       sin->sin_port = 0;
+       sin->sin_len = sizeof(*sin);
+}
+
+char *
+inet_format(sin)
+       struct sockaddr_in *sin;
+{
+       char *inet_ntoa();
+
+       return (inet_ntoa(sin->sin_addr));
+}
diff --git a/routed.tproj/af.h b/routed.tproj/af.h
new file mode 100644 (file)
index 0000000..02f48b0
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * Per address family routines.
+ */
+struct afswitch {
+       int     (*af_hash)();           /* returns keys based on address */
+       int     (*af_netmatch)();       /* verifies net # matching */
+       int     (*af_output)();         /* interprets address for sending */
+       int     (*af_portmatch)();      /* packet from some other router? */
+       int     (*af_portcheck)();      /* packet from privileged peer? */
+       int     (*af_checkhost)();      /* tells if address is valid */
+       int     (*af_rtflags)();        /* get flags for route (host or net) */
+       int     (*af_sendroute)();      /* check bounds of subnet broadcast */
+       int     (*af_canon)();          /* canonicalize address for compares */
+       char    *(*af_format)();        /* convert address to string */
+};
+
+/*
+ * Structure returned by af_hash routines.
+ */
+struct afhash {
+       u_int   afh_hosthash;           /* host based hash */
+       u_int   afh_nethash;            /* network based hash */
+};
+
+extern struct  afswitch afswitch[];    /* table proper */
+extern int     af_max;                 /* number of entries in table */
diff --git a/routed.tproj/defs.c b/routed.tproj/defs.c
new file mode 100644 (file)
index 0000000..5b176bc
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* NeXT */
+#define EXTERN
+#include "defs.h"
diff --git a/routed.tproj/defs.h b/routed.tproj/defs.h
new file mode 100644 (file)
index 0000000..fad0ae1
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+/*
+ * Internal data structure definitions for
+ * user routing process.  Based on Xerox NS
+ * protocol specs with mods relevant to more
+ * general addressing scheme.
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/route.h>
+#include <netinet/in.h>
+#include <protocols/routed.h>
+
+#include <stdio.h>
+#include <netdb.h>
+
+/* NeXT */
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+#include "trace.h"
+#include "interface.h"
+#include "table.h"
+#include "af.h"
+
+/*
+ * When we find any interfaces marked down we rescan the
+ * kernel every CHECK_INTERVAL seconds to see if they've
+ * come up.
+ */
+#define        CHECK_INTERVAL  (1*60)
+
+#define equal(a1, a2) \
+       (memcmp((a1), (a2), sizeof (struct sockaddr)) == 0)
+
+EXTERN struct  sockaddr_in addr;       /* address of daemon's socket */
+
+EXTERN int     s;                      /* source and sink of all data */
+EXTERN int     r;                      /* routing socket */
+EXTERN pid_t   pid;                    /* process id for identifying messages */
+EXTERN uid_t   uid;                    /* user id for identifying messages */
+EXTERN int     seqno;                  /* sequence number for identifying messages */
+EXTERN int     kmem;
+extern int     supplier;               /* process should supply updates */
+extern int     install;                /* if 1 call kernel */
+extern int     lookforinterfaces;      /* if 1 probe kernel for new up interfaces */
+EXTERN int     performnlist;           /* if 1 check if /vmunix has changed */
+extern int     externalinterfaces;     /* # of remote and local interfaces */
+EXTERN struct  timeval now;            /* current idea of time */
+EXTERN struct  timeval lastbcast;      /* last time all/changes broadcast */
+EXTERN struct  timeval lastfullupdate; /* last time full table broadcast */
+EXTERN struct  timeval nextbcast;      /* time to wait before changes broadcast */
+EXTERN int     needupdate;             /* true if we need update at nextbcast */
+
+EXTERN char    packet[MAXPACKETSIZE+1];
+extern struct  rip *msg;
+
+EXTERN char    **argv0;
+EXTERN struct  servent *sp;
+
+EXTERN struct  in_addr inet_makeaddr();
+EXTERN int     inet_addr();
+EXTERN int     inet_maskof();
+EXTERN int     sndmsg();
+EXTERN int     supply();
+EXTERN int     cleanup();
+
+EXTERN int     rtioctl();
+#define ADD 1
+#define DELETE 2
+#define CHANGE 3
diff --git a/routed.tproj/if.c b/routed.tproj/if.c
new file mode 100644 (file)
index 0000000..5235d58
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+extern struct interface *ifnet;
+
+/*
+ * Find the interface with address addr.
+ */
+struct interface *
+if_ifwithaddr(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp;
+
+#define        same(a1, a2) \
+       (memcmp((a1)->sa_data, (a2)->sa_data, 14) == 0)
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_REMOTE)
+                       continue;
+               if (ifp->int_addr.sa_family != addr->sa_family)
+                       continue;
+               if (same(&ifp->int_addr, addr))
+                       break;
+               if ((ifp->int_flags & IFF_BROADCAST) &&
+                   same(&ifp->int_broadaddr, addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find the point-to-point interface with destination address addr.
+ */
+struct interface *
+if_ifwithdstaddr(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp;
+
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if ((ifp->int_flags & IFF_POINTOPOINT) == 0)
+                       continue;
+               if (same(&ifp->int_dstaddr, addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find the interface on the network 
+ * of the specified address.
+ */
+struct interface *
+if_ifwithnet(addr)
+       register struct sockaddr *addr;
+{
+       register struct interface *ifp;
+       register int af = addr->sa_family;
+       register int (*netmatch)();
+
+       if (af >= af_max)
+               return (0);
+       netmatch = afswitch[af].af_netmatch;
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_REMOTE)
+                       continue;
+               if (af != ifp->int_addr.sa_family)
+                       continue;
+               if ((*netmatch)(addr, &ifp->int_addr))
+                       break;
+       }
+       return (ifp);
+}
+
+/*
+ * Find an interface from which the specified address
+ * should have come from.  Used for figuring out which
+ * interface a packet came in on -- for tracing.
+ */
+struct interface *
+if_iflookup(addr)
+       struct sockaddr *addr;
+{
+       register struct interface *ifp, *maybe;
+       register int af = addr->sa_family;
+       register int (*netmatch)();
+
+       if (af >= af_max)
+               return (0);
+       maybe = 0;
+       netmatch = afswitch[af].af_netmatch;
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_addr.sa_family != af)
+                       continue;
+               if (same(&ifp->int_addr, addr))
+                       break;
+               if ((ifp->int_flags & IFF_BROADCAST) &&
+                   same(&ifp->int_broadaddr, addr))
+                       break;
+               if ((ifp->int_flags & IFF_POINTOPOINT) &&
+                   same(&ifp->int_dstaddr, addr))
+                       break;
+               if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr))
+                       maybe = ifp;
+       }
+       if (ifp == 0)
+               ifp = maybe;
+       return (ifp);
+}
diff --git a/routed.tproj/inet.c b/routed.tproj/inet.c
new file mode 100644 (file)
index 0000000..ef194a8
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Temporarily, copy these routines from the kernel,
+ * as we need to know about subnets.
+ */
+#include "defs.h"
+
+extern struct interface *ifnet;
+
+/*
+ * Formulate an Internet address from network + host.
+ */
+__private_extern__
+struct in_addr
+inet_makeaddr(net, host)
+       u_long net, host;
+{
+       register struct interface *ifp;
+       register u_long mask;
+       u_long addr;
+
+       if (IN_CLASSA(net))
+               mask = IN_CLASSA_HOST;
+       else if (IN_CLASSB(net))
+               mask = IN_CLASSB_HOST;
+       else
+               mask = IN_CLASSC_HOST;
+       for (ifp = ifnet; ifp; ifp = ifp->int_next)
+               if ((ifp->int_netmask & net) == ifp->int_net) {
+                       mask = ~ifp->int_subnetmask;
+                       break;
+               }
+       addr = net | (host & mask);
+       addr = htonl(addr);
+       return (*(struct in_addr *)&addr);
+}
+
+/*
+ * Return the network number from an internet address.
+ */
+__private_extern__
+inet_netof(in)
+       struct in_addr in;
+{
+       register u_long i = ntohl(in.s_addr);
+       register u_long net;
+       register struct interface *ifp;
+
+       if (IN_CLASSA(i))
+               net = i & IN_CLASSA_NET;
+       else if (IN_CLASSB(i))
+               net = i & IN_CLASSB_NET;
+       else
+               net = i & IN_CLASSC_NET;
+
+       /*
+        * Check whether network is a subnet;
+        * if so, return subnet number.
+        */
+       for (ifp = ifnet; ifp; ifp = ifp->int_next)
+               if ((ifp->int_netmask & net) == ifp->int_net)
+                       return (i & ifp->int_subnetmask);
+       return (net);
+}
+
+/*
+ * Return the host portion of an internet address.
+ */
+inet_lnaof(in)
+       struct in_addr in;
+{
+       register u_long i = ntohl(in.s_addr);
+       register u_long net, host;
+       register struct interface *ifp;
+
+       if (IN_CLASSA(i)) {
+               net = i & IN_CLASSA_NET;
+               host = i & IN_CLASSA_HOST;
+       } else if (IN_CLASSB(i)) {
+               net = i & IN_CLASSB_NET;
+               host = i & IN_CLASSB_HOST;
+       } else {
+               net = i & IN_CLASSC_NET;
+               host = i & IN_CLASSC_HOST;
+       }
+
+       /*
+        * Check whether network is a subnet;
+        * if so, use the modified interpretation of `host'.
+        */
+       for (ifp = ifnet; ifp; ifp = ifp->int_next)
+               if ((ifp->int_netmask & net) == ifp->int_net)
+                       return (host &~ ifp->int_subnetmask);
+       return (host);
+}
+
+/*
+ * Return the netmask pertaining to an internet address.
+ */
+inet_maskof(inaddr)
+       u_long inaddr;
+{
+       register u_long i = ntohl(inaddr);
+       register u_long mask;
+       register struct interface *ifp;
+
+       if (i == 0) {
+               mask = 0;
+       } else if (IN_CLASSA(i)) {
+               mask = IN_CLASSA_NET;
+       } else if (IN_CLASSB(i)) {
+               mask = IN_CLASSB_NET;
+       } else
+               mask = IN_CLASSC_NET;
+
+       /*
+        * Check whether network is a subnet;
+        * if so, use the modified interpretation of `host'.
+        */
+       for (ifp = ifnet; ifp; ifp = ifp->int_next)
+               if ((ifp->int_netmask & i) == ifp->int_net)
+                       mask = ifp->int_subnetmask;
+       return (htonl(mask));
+}
+
+/*
+ * Return RTF_HOST if the address is
+ * for an Internet host, RTF_SUBNET for a subnet,
+ * 0 for a network.
+ */
+inet_rtflags(sin)
+       struct sockaddr_in *sin;
+{
+       register u_long i = ntohl(sin->sin_addr.s_addr);
+       register u_long net, host;
+       register struct interface *ifp;
+
+       if (IN_CLASSA(i)) {
+               net = i & IN_CLASSA_NET;
+               host = i & IN_CLASSA_HOST;
+       } else if (IN_CLASSB(i)) {
+               net = i & IN_CLASSB_NET;
+               host = i & IN_CLASSB_HOST;
+       } else {
+               net = i & IN_CLASSC_NET;
+               host = i & IN_CLASSC_HOST;
+       }
+
+       /*
+        * Check whether this network is subnetted;
+        * if so, check whether this is a subnet or a host.
+        */
+       for (ifp = ifnet; ifp; ifp = ifp->int_next)
+               if (net == ifp->int_net) {
+                       if (host &~ ifp->int_subnetmask)
+                               return (RTF_HOST);
+                       else if (ifp->int_subnetmask != ifp->int_netmask)
+                               return (RTF_SUBNET);
+                       else
+                               return (0);             /* network */
+               }
+       if (host == 0)
+               return (0);     /* network */
+       else
+               return (RTF_HOST);
+}
+
+/*
+ * Return true if a route to subnet/host of route rt should be sent to dst.
+ * Send it only if dst is on the same logical network if not "internal",
+ * otherwise only if the route is the "internal" route for the logical net.
+ */
+inet_sendroute(rt, dst)
+       struct rt_entry *rt;
+       struct sockaddr_in *dst;
+{
+       register u_long r =
+           ntohl(((struct sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr);
+       register u_long d = ntohl(dst->sin_addr.s_addr);
+
+       if (IN_CLASSA(r)) {
+               if ((r & IN_CLASSA_NET) == (d & IN_CLASSA_NET)) {
+                       if ((r & IN_CLASSA_HOST) == 0)
+                               return ((rt->rt_state & RTS_INTERNAL) == 0);
+                       return (1);
+               }
+               if (r & IN_CLASSA_HOST)
+                       return (0);
+               return ((rt->rt_state & RTS_INTERNAL) != 0);
+       } else if (IN_CLASSB(r)) {
+               if ((r & IN_CLASSB_NET) == (d & IN_CLASSB_NET)) {
+                       if ((r & IN_CLASSB_HOST) == 0)
+                               return ((rt->rt_state & RTS_INTERNAL) == 0);
+                       return (1);
+               }
+               if (r & IN_CLASSB_HOST)
+                       return (0);
+               return ((rt->rt_state & RTS_INTERNAL) != 0);
+       } else {
+               if ((r & IN_CLASSC_NET) == (d & IN_CLASSC_NET)) {
+                       if ((r & IN_CLASSC_HOST) == 0)
+                               return ((rt->rt_state & RTS_INTERNAL) == 0);
+                       return (1);
+               }
+               if (r & IN_CLASSC_HOST)
+                       return (0);
+               return ((rt->rt_state & RTS_INTERNAL) != 0);
+       }
+}
diff --git a/routed.tproj/input.c b/routed.tproj/input.c
new file mode 100644 (file)
index 0000000..d39615f
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+#include <sys/syslog.h>
+
+/*
+ * Process a newly received packet.
+ */
+rip_input(from, rip, size)
+       struct sockaddr *from;
+       register struct rip *rip;
+       int size;
+{
+       register struct rt_entry *rt;
+       register struct netinfo *n;
+       register struct interface *ifp;
+       struct interface *if_ifwithdstaddr();
+       int count, changes = 0;
+       register struct afswitch *afp;
+       static struct sockaddr badfrom, badfrom2;
+
+       ifp = 0;
+       TRACE_INPUT(ifp, from, (char *)rip, size);
+       if (from->sa_family >= af_max ||
+           (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) {
+               syslog(LOG_INFO,
+        "\"from\" address in unsupported address family (%d), cmd %d\n",
+                   from->sa_family, rip->rip_cmd);
+               return;
+       }
+       if (rip->rip_vers == 0) {
+               syslog(LOG_ERR,
+                   "RIP version 0 packet received from %s! (cmd %d)",
+                   (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd);
+               return;
+       }
+       switch (rip->rip_cmd) {
+
+       case RIPCMD_REQUEST:
+               n = rip->rip_nets;
+               count = size - ((char *)n - (char *)rip);
+               if (count < sizeof (struct netinfo))
+                       return;
+               for (; count > 0; n++) {
+                       if (count < sizeof (struct netinfo))
+                               break;
+                       count -= sizeof (struct netinfo);
+
+#if BSD < 198810
+                       if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
+                           n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
+#else
+#define osa(x) ((struct osockaddr *)(&(x)))
+                           n->rip_dst.sa_family =
+                                       ntohs(osa(n->rip_dst)->sa_family);
+                           n->rip_dst.sa_len = sizeof(n->rip_dst);
+#endif
+                       n->rip_metric = ntohl(n->rip_metric);
+                       /* 
+                        * A single entry with sa_family == AF_UNSPEC and
+                        * metric ``infinity'' means ``all routes''.
+                        * We respond to routers only if we are acting
+                        * as a supplier, or to anyone other than a router
+                        * (eg, query).
+                        */
+                       if (n->rip_dst.sa_family == AF_UNSPEC &&
+                           n->rip_metric == HOPCNT_INFINITY && count == 0) {
+                               if (supplier || (*afp->af_portmatch)(from) == 0)
+                                       supply(from, 0, 0, 0);
+                               return;
+                       }
+                       if (n->rip_dst.sa_family < af_max &&
+                           afswitch[n->rip_dst.sa_family].af_hash)
+                               rt = rtlookup(&n->rip_dst);
+                       else
+                               rt = 0;
+#define min(a, b) (a < b ? a : b)
+                       n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
+                               min(rt->rt_metric + 1, HOPCNT_INFINITY);
+#if BSD < 198810
+                       if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
+                           n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
+#else
+                           osa(n->rip_dst)->sa_family =
+                                               htons(n->rip_dst.sa_family);
+#endif
+                       n->rip_metric = htonl(n->rip_metric);
+               }
+               rip->rip_cmd = RIPCMD_RESPONSE;
+               memmove(packet, rip, size);
+               (*afp->af_output)(s, 0, from, size);
+               return;
+
+       case RIPCMD_TRACEON:
+       case RIPCMD_TRACEOFF:
+               /* verify message came from a privileged port */
+               if ((*afp->af_portcheck)(from) == 0)
+                       return;
+               if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
+                   (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
+                   ifp->int_flags & IFF_PASSIVE) {
+                       syslog(LOG_ERR, "trace command from unknown router, %s",
+                           (*afswitch[from->sa_family].af_format)(from));
+                       return;
+               }
+               ((char *)rip)[size] = '\0';
+               if (rip->rip_cmd == RIPCMD_TRACEON)
+                       traceon(rip->rip_tracefile);
+               else
+                       traceoff();
+               return;
+
+       case RIPCMD_RESPONSE:
+               /* verify message came from a router */
+               if ((*afp->af_portmatch)(from) == 0)
+                       return;
+               (*afp->af_canon)(from);
+               /* are we talking to ourselves? */
+               ifp = if_ifwithaddr(from);
+               if (ifp) {
+                       if (ifp->int_flags & IFF_PASSIVE) {
+                               syslog(LOG_ERR,
+                                 "bogus input (from passive interface, %s)",
+                                 (*afswitch[from->sa_family].af_format)(from));
+                               return;
+                       }
+                       rt = rtfind(from);
+                       if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) &&
+                           rt->rt_metric >= ifp->int_metric) 
+                               addrouteforif(ifp);
+                       else
+                               rt->rt_timer = 0;
+                       return;
+               }
+               /*
+                * Update timer for interface on which the packet arrived.
+                * If from other end of a point-to-point link that isn't
+                * in the routing tables, (re-)add the route.
+                */
+               if ((rt = rtfind(from)) &&
+                   (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
+                       rt->rt_timer = 0;
+               else if ((ifp = if_ifwithdstaddr(from)) &&
+                   (rt == 0 || rt->rt_metric >= ifp->int_metric))
+                       addrouteforif(ifp);
+               /*
+                * "Authenticate" router from which message originated.
+                * We accept routing packets from routers directly connected
+                * via broadcast or point-to-point networks,
+                * and from those listed in /etc/gateways.
+                */
+               if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
+                   (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
+                   ifp->int_flags & IFF_PASSIVE) {
+                       if (memcmp(from, &badfrom, sizeof(badfrom)) != 0) {
+                               syslog(LOG_ERR,
+                                 "packet from unknown router, %s",
+                                 (*afswitch[from->sa_family].af_format)(from));
+                               badfrom = *from;
+                       }
+                       return;
+               }
+               size -= 4 * sizeof (char);
+               n = rip->rip_nets;
+               for (; size > 0; size -= sizeof (struct netinfo), n++) {
+                       if (size < sizeof (struct netinfo))
+                               break;
+#if BSD < 198810
+                       if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
+                               n->rip_dst.sa_family =
+                                       ntohs(n->rip_dst.sa_family);
+#else
+                           n->rip_dst.sa_family =
+                                       ntohs(osa(n->rip_dst)->sa_family);
+                           n->rip_dst.sa_len = sizeof(n->rip_dst);
+#endif
+                       n->rip_metric = ntohl(n->rip_metric);
+                       if (n->rip_dst.sa_family >= af_max ||
+                           (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
+                           (int (*)())0) {
+                               syslog(LOG_INFO,
+               "route in unsupported address family (%d), from %s (af %d)\n",
+                                  n->rip_dst.sa_family,
+                                  (*afswitch[from->sa_family].af_format)(from),
+                                  from->sa_family);
+                               continue;
+                       }
+                       if (((*afp->af_checkhost)(&n->rip_dst)) == 0) {
+                               syslog(LOG_DEBUG,
+                                   "bad host in route from %s (af %d)\n",
+                                  (*afswitch[from->sa_family].af_format)(from),
+                                  from->sa_family);
+                               continue;
+                       }
+                       if (n->rip_metric == 0 ||
+                           (unsigned) n->rip_metric > HOPCNT_INFINITY) {
+                               if (memcmp(from, &badfrom2,
+                                   sizeof(badfrom2)) != 0) {
+                                       syslog(LOG_ERR,
+                                           "bad metric (%d) from %s\n",
+                                           n->rip_metric,
+                                 (*afswitch[from->sa_family].af_format)(from));
+                                       badfrom2 = *from;
+                               }
+                               continue;
+                       }
+                       /*
+                        * Adjust metric according to incoming interface.
+                        */
+                       if ((unsigned) n->rip_metric < HOPCNT_INFINITY)
+                               n->rip_metric += ifp->int_metric;
+                       if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
+                               n->rip_metric = HOPCNT_INFINITY;
+                       rt = rtlookup(&n->rip_dst);
+                       if (rt == 0 ||
+                           (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
+                           (RTS_INTERNAL|RTS_INTERFACE)) {
+                               /*
+                                * If we're hearing a logical network route
+                                * back from a peer to which we sent it,
+                                * ignore it.
+                                */
+                               if (rt && rt->rt_state & RTS_SUBNET &&
+                                   (*afp->af_sendroute)(rt, from))
+                                       continue;
+                               if ((unsigned)n->rip_metric < HOPCNT_INFINITY) {
+                                   /*
+                                    * Look for an equivalent route that
+                                    * includes this one before adding
+                                    * this route.
+                                    */
+                                   rt = rtfind(&n->rip_dst);
+                                   if (rt && equal(from, &rt->rt_router))
+                                           continue;
+                                   rtadd(&n->rip_dst, from, n->rip_metric, 0);
+                                   changes++;
+                               }
+                               continue;
+                       }
+
+                       /*
+                        * Update if from gateway and different,
+                        * shorter, or equivalent but old route
+                        * is getting stale.
+                        */
+                       if (equal(from, &rt->rt_router)) {
+                               if (n->rip_metric != rt->rt_metric) {
+                                       rtchange(rt, from, n->rip_metric);
+                                       changes++;
+                                       rt->rt_timer = 0;
+                                       if (rt->rt_metric >= HOPCNT_INFINITY)
+                                               rt->rt_timer =
+                                                   GARBAGE_TIME - EXPIRE_TIME;
+                               } else if (rt->rt_metric < HOPCNT_INFINITY)
+                                       rt->rt_timer = 0;
+                       } else if ((unsigned) n->rip_metric < rt->rt_metric ||
+                           (rt->rt_metric == n->rip_metric &&
+                           rt->rt_timer > (EXPIRE_TIME/2) &&
+                           (unsigned) n->rip_metric < HOPCNT_INFINITY)) {
+                               rtchange(rt, from, n->rip_metric);
+                               changes++;
+                               rt->rt_timer = 0;
+                       }
+               }
+               break;
+       }
+
+       /*
+        * If changes have occurred, and if we have not sent a broadcast
+        * recently, send a dynamic update.  This update is sent only
+        * on interfaces other than the one on which we received notice
+        * of the change.  If we are within MIN_WAITTIME of a full update,
+        * don't bother sending; if we just sent a dynamic update
+        * and set a timer (nextbcast), delay until that time.
+        * If we just sent a full update, delay the dynamic update.
+        * Set a timer for a randomized value to suppress additional
+        * dynamic updates until it expires; if we delayed sending
+        * the current changes, set needupdate.
+        */
+       if (changes && supplier &&
+          now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) {
+               u_long delay;
+               extern long random();
+
+               if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME &&
+                   timercmp(&nextbcast, &now, <)) {
+                       if (traceactions)
+                               fprintf(ftrace, "send dynamic update\n");
+                       toall(supply, RTS_CHANGED, ifp);
+                       lastbcast = now;
+                       needupdate = 0;
+                       nextbcast.tv_sec = 0;
+               } else {
+                       needupdate++;
+                       if (traceactions)
+                               fprintf(ftrace, "delay dynamic update\n");
+               }
+#define RANDOMDELAY()  (MIN_WAITTIME * 1000000 + \
+               (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000))
+
+               if (nextbcast.tv_sec == 0) {
+                       delay = RANDOMDELAY();
+                       if (traceactions)
+                               fprintf(ftrace,
+                                   "inhibit dynamic update for %d usec\n",
+                                   delay);
+                       nextbcast.tv_sec = delay / 1000000;
+                       nextbcast.tv_usec = delay % 1000000;
+                       timevaladd(&nextbcast, &now);
+                       /*
+                        * If the next possibly dynamic update
+                        * is within MIN_WAITTIME of the next full update,
+                        * force the delay past the full update,
+                        * or we might send a dynamic update just before
+                        * the full update.
+                        */
+                       if (nextbcast.tv_sec > lastfullupdate.tv_sec +
+                           SUPPLY_INTERVAL - MIN_WAITTIME)
+                               nextbcast.tv_sec = lastfullupdate.tv_sec +
+                                   SUPPLY_INTERVAL + 1;
+               }
+       }
+}
diff --git a/routed.tproj/interface.h b/routed.tproj/interface.h
new file mode 100644 (file)
index 0000000..8e2df84
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * An ``interface'' is similar to an ifnet structure,
+ * except it doesn't contain q'ing info, and it also
+ * handles ``logical'' interfaces (remote gateways
+ * that we want to keep polling even if they go down).
+ * The list of interfaces which we maintain is used
+ * in supplying the gratuitous routing table updates.
+ */
+struct interface {
+       struct  interface *int_next;
+       struct  sockaddr int_addr;              /* address on this host */
+       union {
+               struct  sockaddr intu_broadaddr;
+               struct  sockaddr intu_dstaddr;
+       } int_intu;
+#define        int_broadaddr   int_intu.intu_broadaddr /* broadcast address */
+#define        int_dstaddr     int_intu.intu_dstaddr   /* other end of p-to-p link */
+       int     int_metric;                     /* init's routing entry */
+       int     int_flags;                      /* see below */
+       /* START INTERNET SPECIFIC */
+       u_long  int_net;                        /* network # */
+       u_long  int_netmask;                    /* net mask for addr */
+       u_long  int_subnet;                     /* subnet # */
+       u_long  int_subnetmask;                 /* subnet mask for addr */
+       /* END INTERNET SPECIFIC */
+       struct  ifdebug int_input, int_output;  /* packet tracing stuff */
+       int     int_ipackets;                   /* input packets received */
+       int     int_opackets;                   /* output packets sent */
+       char    *int_name;                      /* from kernel if structure */
+       u_short int_transitions;                /* times gone up-down */
+};
+
+/*
+ * 0x1 to 0x10 are reused from the kernel's ifnet definitions,
+ * the others agree with the RTS_ flags defined elsewhere.
+ */
+#define        IFF_UP          0x1             /* interface is up */
+#define        IFF_BROADCAST   0x2             /* broadcast address valid */
+#define        IFF_DEBUG       0x4             /* turn on debugging */
+#define        IFF_LOOPBACK    0x8             /* software loopback net */
+#define        IFF_POINTOPOINT 0x10            /* interface is point-to-point link */
+
+#define        IFF_SUBNET      0x100000        /* interface on subnetted network */
+#define        IFF_PASSIVE     0x200000        /* can't tell if up/down */
+#define        IFF_INTERFACE   0x400000        /* hardware interface */
+#define        IFF_REMOTE      0x800000        /* interface isn't on this machine */
+
+struct interface *if_ifwithaddr();
+struct interface *if_ifwithdstaddr();
+struct interface *if_ifwithnet();
+struct interface *if_iflookup();
diff --git a/routed.tproj/main.c b/routed.tproj/main.c
new file mode 100644 (file)
index 0000000..43597a5
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#include <net/if.h>
+
+#include <sys/errno.h>
+#include <sys/signal.h>
+#include <sys/syslog.h>
+#include "pathnames.h"
+
+int    supplier = -1;          /* process should supply updates */
+int    gateway = 0;            /* 1 if we are a gateway to parts beyond */
+int    debug = 0;
+int    bufspace = 127*1024;    /* max. input buffer size to request */
+
+struct rip *msg = (struct rip *)packet;
+void   hup(), rtdeleteall(), sigtrace(), timer();
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int n, cc, nfd, omask, tflags = 0;
+       struct sockaddr from;
+       struct timeval *tvp, waittime;
+       struct itimerval itval;
+       register struct rip *query = msg;
+       fd_set ibits;
+       u_char retry;
+       
+       argv0 = argv;
+#if BSD >= 43
+       openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+       setlogmask(LOG_UPTO(LOG_WARNING));
+#else
+       openlog("routed", LOG_PID);
+#define LOG_UPTO(x) (x)
+#define setlogmask(x) (x)
+#endif
+       sp = getservbyname("router", "udp");
+       if (sp == NULL) {
+               fprintf(stderr, "routed: router/udp: unknown service\n");
+               exit(1);
+       }
+       addr.sin_family = AF_INET;
+       addr.sin_port = sp->s_port;
+       r = socket(AF_ROUTE, SOCK_RAW, 0);
+       /* later, get smart about lookingforinterfaces */
+       if (r)
+               shutdown(r, 0); /* for now, don't want reponses */
+       else {
+               fprintf(stderr, "routed: no routing socket\n");
+               exit(1);
+       }
+       s = getsocket(AF_INET, SOCK_DGRAM, &addr);
+       if (s < 0)
+               exit(1);
+       argv++, argc--;
+       while (argc > 0 && **argv == '-') {
+               if (strcmp(*argv, "-s") == 0) {
+                       supplier = 1;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-q") == 0) {
+                       supplier = 0;
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-t") == 0) {
+                       tflags++;
+                       setlogmask(LOG_UPTO(LOG_DEBUG));
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-d") == 0) {
+                       debug++;
+                       setlogmask(LOG_UPTO(LOG_DEBUG));
+                       argv++, argc--;
+                       continue;
+               }
+               if (strcmp(*argv, "-g") == 0) {
+                       gateway = 1;
+                       argv++, argc--;
+                       continue;
+               }
+               fprintf(stderr,
+                       "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
+               exit(1);
+       }
+
+       if (debug == 0 && tflags == 0)
+               daemon(0, 0);
+       /*
+        * Any extra argument is considered
+        * a tracing log file.
+        */
+       if (argc > 0)
+               traceon(*argv);
+       while (tflags-- > 0)
+               bumploglevel();
+
+       (void) gettimeofday(&now, (struct timezone *)NULL);
+       /*
+        * Collect an initial view of the world by
+        * checking the interface configuration and the gateway kludge
+        * file.  Then, send a request packet on all
+        * directly connected networks to find out what
+        * everyone else thinks.
+        */
+       rtinit();
+       ifinit();
+       gwkludge();
+       if (gateway > 0)
+               rtdefault();
+       if (supplier < 0)
+               supplier = 0;
+       query->rip_cmd = RIPCMD_REQUEST;
+       query->rip_vers = RIPVERSION;
+       if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1)   /* XXX */
+               query->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC);
+       else
+               query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
+       query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY);
+       toall(sndmsg);
+       signal(SIGALRM, timer);
+       signal(SIGHUP, hup);
+       signal(SIGTERM, hup);
+       signal(SIGINT, rtdeleteall);
+       signal(SIGUSR1, sigtrace);
+       signal(SIGUSR2, sigtrace);
+       itval.it_interval.tv_sec = TIMER_RATE;
+       itval.it_value.tv_sec = TIMER_RATE;
+       itval.it_interval.tv_usec = 0;
+       itval.it_value.tv_usec = 0;
+       srandom(getpid());
+       if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
+               syslog(LOG_ERR, "setitimer: %m\n");
+
+       FD_ZERO(&ibits);
+       nfd = s + 1;                    /* 1 + max(fd's) */
+       for (;;) {
+               FD_SET(s, &ibits);
+               /*
+                * If we need a dynamic update that was held off,
+                * needupdate will be set, and nextbcast is the time
+                * by which we want select to return.  Compute time
+                * until dynamic update should be sent, and select only
+                * until then.  If we have already passed nextbcast,
+                * just poll.
+                */
+               if (needupdate) {
+                       waittime = nextbcast;
+                       timevalsub(&waittime, &now);
+                       if (waittime.tv_sec < 0) {
+                               waittime.tv_sec = 0;
+                               waittime.tv_usec = 0;
+                       }
+                       if (traceactions)
+                               fprintf(ftrace,
+                                "select until dynamic update %d/%d sec/usec\n",
+                                   waittime.tv_sec, waittime.tv_usec);
+                       tvp = &waittime;
+               } else
+                       tvp = (struct timeval *)NULL;
+               n = select(nfd, &ibits, 0, 0, tvp);
+               if (n <= 0) {
+                       /*
+                        * Need delayed dynamic update if select returned
+                        * nothing and we timed out.  Otherwise, ignore
+                        * errors (e.g. EINTR).
+                        */
+                       if (n < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                               syslog(LOG_ERR, "select: %m");
+                       }
+                       omask = sigblock(sigmask(SIGALRM));
+                       if (n == 0 && needupdate) {
+                               if (traceactions)
+                                       fprintf(ftrace,
+                                           "send delayed dynamic update\n");
+                               (void) gettimeofday(&now,
+                                           (struct timezone *)NULL);
+                               toall(supply, RTS_CHANGED,
+                                   (struct interface *)NULL);
+                               lastbcast = now;
+                               needupdate = 0;
+                               nextbcast.tv_sec = 0;
+                       }
+                       sigsetmask(omask);
+                       continue;
+               }
+               (void) gettimeofday(&now, (struct timezone *)NULL);
+               omask = sigblock(sigmask(SIGALRM));
+#ifdef doesntwork
+/*
+printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n",
+       s,
+       ibits.fds_bits[0],
+       (s)/(sizeof(fd_mask) * 8),
+       ((s) % (sizeof(fd_mask) * 8)),
+       (1 << ((s) % (sizeof(fd_mask) * 8))),
+       ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
+       &ibits
+       );
+*/
+               if (FD_ISSET(s, &ibits))
+#else
+               if (ibits.fds_bits[s/32] & (1 << s))
+#endif
+                       process(s);
+               /* handle ICMP redirects */
+               sigsetmask(omask);
+       }
+}
+
+timevaladd(t1, t2)
+       struct timeval *t1, *t2;
+{
+
+       t1->tv_sec += t2->tv_sec;
+       if ((t1->tv_usec += t2->tv_usec) > 1000000) {
+               t1->tv_sec++;
+               t1->tv_usec -= 1000000;
+       }
+}
+
+timevalsub(t1, t2)
+       struct timeval *t1, *t2;
+{
+
+       t1->tv_sec -= t2->tv_sec;
+       if ((t1->tv_usec -= t2->tv_usec) < 0) {
+               t1->tv_sec--;
+               t1->tv_usec += 1000000;
+       }
+}
+
+process(fd)
+       int fd;
+{
+       struct sockaddr from;
+       int fromlen, cc;
+       union {
+               char    buf[MAXPACKETSIZE+1];
+               struct  rip rip;
+       } inbuf;
+
+       for (;;) {
+               fromlen = sizeof (from);
+               cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen);
+               if (cc <= 0) {
+                       if (cc < 0 && errno != EWOULDBLOCK)
+                               perror("recvfrom");
+                       break;
+               }
+               if (fromlen != sizeof (struct sockaddr_in))
+                       break;
+               rip_input(&from, &inbuf.rip, cc);
+       }
+}
+
+getsocket(domain, type, sin)
+       int domain, type;
+       struct sockaddr_in *sin;
+{
+       int sock, on = 1;
+
+       if ((sock = socket(domain, type, 0)) < 0) {
+               perror("socket");
+               syslog(LOG_ERR, "socket: %m");
+               return (-1);
+       }
+#ifdef SO_BROADCAST
+       if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+               syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+               close(sock);
+               return (-1);
+       }
+#endif
+#ifdef SO_RCVBUF
+       for (on = bufspace; ; on -= 1024) {
+               if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+                   &on, sizeof (on)) == 0)
+                       break;
+               if (on <= 8*1024) {
+                       syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
+                       break;
+               }
+       }
+       if (traceactions)
+               fprintf(ftrace, "recv buf %d\n", on);
+#endif
+       if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) {
+               perror("bind");
+               syslog(LOG_ERR, "bind: %m");
+               close(sock);
+               return (-1);
+       }
+       if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
+               syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
+       return (sock);
+}
diff --git a/routed.tproj/output.c b/routed.tproj/output.c
new file mode 100644 (file)
index 0000000..168c320
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+/*
+ * Apply the function "f" to all non-passive
+ * interfaces.  If the interface supports the
+ * use of broadcasting use it, otherwise address
+ * the output to the known router.
+ */
+toall(f, rtstate, skipif)
+       int (*f)();
+       int rtstate;
+       struct interface *skipif;
+{
+       register struct interface *ifp;
+       register struct sockaddr *dst;
+       register int flags;
+       extern struct interface *ifnet;
+
+       for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+               if (ifp->int_flags & IFF_PASSIVE || ifp == skipif)
+                       continue;
+               dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
+                     ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
+                     &ifp->int_addr;
+               flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
+               (*f)(dst, flags, ifp, rtstate);
+       }
+}
+
+/*
+ * Output a preformed packet.
+ */
+/*ARGSUSED*/
+sndmsg(dst, flags, ifp, rtstate)
+       struct sockaddr *dst;
+       int flags;
+       struct interface *ifp;
+       int rtstate;
+{
+
+       (*afswitch[dst->sa_family].af_output)(s, flags,
+               dst, sizeof (struct rip));
+       TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
+}
+
+/*
+ * Supply dst with the contents of the routing tables.
+ * If this won't fit in one packet, chop it up into several.
+ */
+supply(dst, flags, ifp, rtstate)
+       struct sockaddr *dst;
+       int flags;
+       register struct interface *ifp;
+       int rtstate;
+{
+       register struct rt_entry *rt;
+       register struct netinfo *n = msg->rip_nets;
+       register struct rthash *rh;
+       struct rthash *base = hosthash;
+       int doinghost = 1, size;
+       int (*output)() = afswitch[dst->sa_family].af_output;
+       int (*sendroute)() = afswitch[dst->sa_family].af_sendroute;
+       int npackets = 0;
+
+       msg->rip_cmd = RIPCMD_RESPONSE;
+       msg->rip_vers = RIPVERSION;
+       memset(msg->rip_res1, 0, sizeof(msg->rip_res1));
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
+       for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+               /*
+                * Don't resend the information on the network
+                * from which it was received (unless sending
+                * in response to a query).
+                */
+               if (ifp && rt->rt_ifp == ifp &&
+                   (rt->rt_state & RTS_INTERFACE) == 0)
+                       continue;
+               if (rt->rt_state & RTS_EXTERNAL)
+                       continue;
+               /*
+                * For dynamic updates, limit update to routes
+                * with the specified state.
+                */
+               if (rtstate && (rt->rt_state & rtstate) == 0)
+                       continue;
+               /*
+                * Limit the spread of subnet information
+                * to those who are interested.
+                */
+               if (doinghost == 0 && rt->rt_state & RTS_SUBNET) {
+                       if (rt->rt_dst.sa_family != dst->sa_family)
+                               continue;
+                       if ((*sendroute)(rt, dst) == 0)
+                               continue;
+               }
+               size = (char *)n - packet;
+               if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
+                       TRACE_OUTPUT(ifp, dst, size);
+                       (*output)(s, flags, dst, size);
+                       /*
+                        * If only sending to ourselves,
+                        * one packet is enough to monitor interface.
+                        */
+                       if (ifp && (ifp->int_flags &
+                          (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0)
+                               return;
+                       n = msg->rip_nets;
+                       npackets++;
+               }
+               n->rip_dst = rt->rt_dst;
+#if BSD < 198810
+               if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
+               n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
+#else
+#define osa(x) ((struct osockaddr *)(&(x)))
+               osa(n->rip_dst)->sa_family = htons(n->rip_dst.sa_family);
+#endif
+               n->rip_metric = htonl(rt->rt_metric);
+               n++;
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) {
+               size = (char *)n - packet;
+               TRACE_OUTPUT(ifp, dst, size);
+               (*output)(s, flags, dst, size);
+       }
+}
diff --git a/routed.tproj/pathnames.h b/routed.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..12482f7
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+#include <paths.h>
+
+#define        _PATH_GATEWAYS  "/etc/gateways"
diff --git a/routed.tproj/routed.8 b/routed.tproj/routed.8
new file mode 100644 (file)
index 0000000..8d9ea20
--- /dev/null
@@ -0,0 +1,358 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)routed.8   8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt ROUTED 8
+.Os BSD 4.2
+.Sh NAME
+.Nm routed
+.Nd network routing daemon
+.Sh SYNOPSIS
+.Nm routed
+.Op Fl d
+.Op Fl g
+.Op Fl q
+.Op Fl s
+.Op Fl t
+.Op Ar logfile
+.Sh DESCRIPTION
+.Nm Routed
+is invoked at boot time to manage the network routing tables.
+The routing daemon uses a variant of the Xerox NS Routing
+Information Protocol in maintaining up to date kernel routing
+table entries.
+It used a generalized protocol capable of use with multiple
+address types, but is currently used only for Internet routing
+within a cluster of networks.
+.Pp
+In normal operation
+.Nm routed
+listens on the
+.Xr udp 4
+socket for the
+.Xr route 8
+service (see
+.Xr services 5 )
+for routing information packets.  If the host is an
+internetwork router, it periodically supplies copies
+of its routing tables to any directly connected hosts
+and networks.
+.Pp
+When
+.Nm routed
+is started, it uses the
+.Dv SIOCGIFCONF
+.Xr ioctl 2
+to find those
+directly connected interfaces configured into the
+system and marked ``up'' (the software loopback interface
+is ignored).  If multiple interfaces
+are present, it is assumed that the host will forward packets
+between networks.
+.Nm Routed
+then transmits a 
+.Em request
+packet on each interface (using a broadcast packet if
+the interface supports it) and enters a loop, listening
+for
+.Em request
+and
+.Em response
+packets from other hosts.
+.Pp
+When a
+.Em request
+packet is received, 
+.Nm routed
+formulates a reply based on the information maintained in its
+internal tables.  The
+.Em response
+packet generated contains a list of known routes, each marked
+with a ``hop count'' metric (a count of 16, or greater, is
+considered ``infinite'').  The metric associated with each
+route returned provides a metric
+.Em relative to the sender .
+.Pp
+.Em Response
+packets received by
+.Nm routed
+are used to update the routing tables if one of the following
+conditions is satisfied:
+.Bl -enum
+.It
+No routing table entry exists for the destination network
+or host, and the metric indicates the destination is ``reachable''
+(i.e. the hop count is not infinite).
+.It
+The source host of the packet is the same as the router in the
+existing routing table entry.  That is, updated information is
+being received from the very internetwork router through which
+packets for the destination are being routed.
+.It
+The existing entry in the routing table has not been updated for
+some time (defined to be 90 seconds) and the route is at least
+as cost effective as the current route.
+.It
+The new route describes a shorter route to the destination than
+the one currently stored in the routing tables; the metric of
+the new route is compared against the one stored in the table
+to decide this.
+.El
+.Pp
+When an update is applied,
+.Nm routed
+records the change in its internal tables and updates the kernel
+routing table.
+The change is reflected in the next
+.Em response
+packet sent.
+.Pp
+In addition to processing incoming packets,
+.Nm routed
+also periodically checks the routing table entries.
+If an entry has not been updated for 3 minutes, the entry's metric
+is set to infinity and marked for deletion.  Deletions are delayed
+an additional 60 seconds to insure the invalidation is propagated
+throughout the local internet.
+.Pp
+Hosts acting as internetwork routers gratuitously supply their
+routing tables every 30 seconds to all directly connected hosts
+and networks.
+The response is sent to the broadcast address on nets capable of that function,
+to the destination address on point-to-point links, and to the router's
+own address on other networks.
+The normal routing tables are bypassed when sending gratuitous responses.
+The reception of responses on each network is used to determine that the
+network and interface are functioning correctly.
+If no response is received on an interface, another route may be chosen
+to route around the interface, or the route may be dropped if no alternative
+is available.
+.Pp
+Options supported by
+.Nm routed :
+.Bl -tag -width Ds
+.It Fl d
+Enable additional debugging information to be logged,
+such as bad packets received.
+.It Fl g
+This flag is used on internetwork routers to offer a route
+to the ``default'' destination.
+This is typically used on a gateway to the Internet,
+or on a gateway that uses another routing protocol whose routes
+are not reported to other local routers.
+.It Fl s
+Supplying this
+option forces 
+.Nm routed
+to supply routing information whether it is acting as an internetwork
+router or not.
+This is the default if multiple network interfaces are present,
+or if a point-to-point link is in use.
+.It Fl q
+This
+is the opposite of the
+.Fl s
+option.
+.It Fl t
+If the
+.Fl t
+option is specified, all packets sent or received are
+printed on the standard output.  In addition,
+.Nm routed
+will not divorce itself from the controlling terminal
+so that interrupts from the keyboard will kill the process.
+.El
+.Pp
+Any other argument supplied is interpreted as the name
+of file in which 
+.Nm routed Ns \'s
+actions should be logged.  This log contains information
+about any changes to the routing tables and, if not tracing all packets,
+a history of recent messages sent and received which are related to
+the changed route.
+.Pp
+In addition to the facilities described above, 
+.Nm routed
+supports the notion of ``distant''
+.Em passive
+and 
+.Em active
+gateways.  When 
+.Nm routed
+is started up, it reads the file
+.Pa /etc/gateways
+to find gateways which may not be located using
+only information from the
+.Dv SIOGIFCONF
+.Xr ioctl 2 .
+Gateways specified in this manner should be marked passive
+if they are not expected to exchange routing information,
+while gateways marked active
+should be willing to exchange routing information (i.e.
+they should have a
+.Nm routed
+process running on the machine).
+Routes through passive gateways are installed in the
+kernel's routing tables once upon startup.
+Such routes are not included in
+any routing information transmitted.
+Active gateways are treated equally to network
+interfaces.  Routing information is distributed
+to the gateway and if no routing information is
+received for a period of time, the associated
+route is deleted.
+Gateways marked
+.Em external
+are also passive, but are not placed in the kernel
+routing table nor are they included in routing updates.
+The function of external entries is to inform
+.Nm routed
+that another routing process
+will install such a route, and that alternate routes to that destination
+should not be installed.
+Such entries are only required when both routers may learn of routes
+to the same destination.
+.Pp
+The 
+.Pa /etc/gateways
+is comprised of a series of lines, each in
+the following format:
+.Bd -ragged
+.Pf < Cm net No \&|
+.Cm host Ns >
+.Ar name1
+.Cm gateway
+.Ar name2
+.Cm metric
+.Ar value
+.Pf < Cm passive No \&|
+.Cm active No \&|
+.Cm external Ns >
+.Ed
+.Pp
+The 
+.Cm net
+or
+.Cm host
+keyword indicates if the route is to a network or specific host.
+.Pp
+.Ar Name1
+is the name of the destination network or host.  This may be a
+symbolic name located in
+.Pa /etc/networks
+or
+.Pa /etc/hosts
+(or, if started after
+.Xr named 8 ,
+known to the name server), 
+or an Internet address specified in ``dot'' notation; see
+.Xr inet 3 .
+.Pp
+.Ar Name2
+is the name or address of the gateway to which messages should
+be forwarded.
+.Pp
+.Ar Value
+is a metric indicating the hop count to the destination host
+or network.
+.Pp
+One of the keywords
+.Cm passive ,
+.Cm active
+or
+.Cm external
+indicates if the gateway should be treated as 
+.Em passive
+or
+.Em active
+(as described above),
+or whether the gateway is
+.Em external
+to the scope of the
+.Nm routed
+protocol.
+.Pp
+Internetwork routers that are directly attached to the Arpanet or Milnet
+should use the Exterior Gateway Protocol
+.Pq Tn EGP
+to gather routing information
+rather then using a static routing table of passive gateways.
+.Tn EGP
+is required in order to provide routes for local networks to the rest
+of the Internet system.
+.Sh FILES
+.Bl -tag -width /etc/gateways -compact
+.It Pa /etc/gateways
+for distant gateways
+.El
+.Sh SEE ALSO
+.Xr udp 4 ,
+.Xr icmp 4 ,
+.Xr XNSrouted 8 ,
+.Xr htable 8
+.Rs
+.%T Internet Transport Protocols
+.%R XSIS 028112
+.%Q Xerox System Integration Standard
+.Re
+.Sh BUGS
+The kernel's routing tables may not correspond to those of
+.Nm routed
+when redirects change or add routes.
+.Nm Routed
+should note any redirects received by reading
+the
+.Tn ICMP
+packets received via a raw socket.
+.Pp
+.Nm Routed
+should incorporate other routing protocols,
+such as Xerox
+.Tn \&NS
+.Pq Xr XNSrouted 8
+and
+.Tn EGP .
+Using separate processes for each requires configuration options
+to avoid redundant or competing routes.
+.Pp
+.Nm Routed
+should listen to intelligent interfaces, such as an
+.Tn IMP ,
+to gather more information.
+It does not always detect unidirectional failures in network interfaces
+(e.g., when the output side fails).
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/routed.tproj/startup.c b/routed.tproj/startup.c
new file mode 100644 (file)
index 0000000..c183ac6
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include "pathnames.h"
+
+struct interface *ifnet;
+struct interface **ifnext = &ifnet;
+int    lookforinterfaces = 1;
+int    externalinterfaces = 0;         /* # of remote and local interfaces */
+int    foundloopback;                  /* valid flag for loopaddr */
+struct sockaddr loopaddr;              /* our address on loopback */
+
+
+void
+quit(s)
+       char *s;
+{
+       extern int errno;
+       int sverrno = errno;
+
+       (void) fprintf(stderr, "route: ");
+       if (s)
+               (void) fprintf(stderr, "%s: ", s);
+       (void) fprintf(stderr, "%s\n", strerror(sverrno));
+       exit(1);
+       /* NOTREACHED */
+}
+
+struct rt_addrinfo info;
+/* Sleazy use of local variables throughout file, warning!!!! */
+#define netmask        info.rti_info[RTAX_NETMASK]
+#define ifaaddr        info.rti_info[RTAX_IFA]
+#define brdaddr        info.rti_info[RTAX_BRD]
+
+#define ROUNDUP(a) \
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+void
+rt_xaddrs(cp, cplim, rtinfo)
+       register caddr_t cp, cplim;
+       register struct rt_addrinfo *rtinfo;
+{
+       register struct sockaddr *sa;
+       register int i;
+
+       memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
+       for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+               if ((rtinfo->rti_addrs & (1 << i)) == 0)
+                       continue;
+               rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+               ADVANCE(cp, sa);
+       }
+}
+
+/*
+ * Find the network interfaces which have configured themselves.
+ * If the interface is present but not yet up (for example an
+ * ARPANET IMP), set the lookforinterfaces flag so we'll
+ * come back later and look again.
+ */
+ifinit()
+{
+       struct interface ifs, *ifp;
+       size_t needed;
+       int mib[6], no_ipaddr = 0, flags = 0;
+       char *buf, *cplim, *cp;
+       register struct if_msghdr *ifm;
+       register struct ifa_msghdr *ifam;
+       struct sockaddr_dl *sdl;
+        struct sockaddr_in *sin;
+       u_long i;
+
+        mib[0] = CTL_NET;
+        mib[1] = PF_ROUTE;
+        mib[2] = 0;
+        mib[3] = AF_INET;
+        mib[4] = NET_RT_IFLIST;
+        mib[5] = 0;
+        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+                quit("route-sysctl-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               quit("malloc");
+        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+               quit("actual retrieval of interface table");
+       lookforinterfaces = 0;
+       cplim = buf + needed;
+       for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
+               ifm = (struct if_msghdr *)cp;
+               if (ifm->ifm_type == RTM_IFINFO) {
+                       memset(&ifs, 0, sizeof(ifs));
+                       ifs.int_flags = flags = (0xffff & ifm->ifm_flags) | IFF_INTERFACE;
+                       if ((flags & IFF_UP) == 0 || no_ipaddr)
+                               lookforinterfaces = 1;
+                       sdl = (struct sockaddr_dl *) (ifm + 1);
+                       sdl->sdl_data[sdl->sdl_nlen] = 0;
+                       no_ipaddr = 1;
+                       continue;
+               }
+               if (ifm->ifm_type != RTM_NEWADDR)
+                       quit("ifinit: out of sync");
+               if ((flags & IFF_UP) == 0)
+                       continue;
+               ifam = (struct ifa_msghdr *)ifm;
+               info.rti_addrs = ifam->ifam_addrs;
+               rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
+               if (ifaaddr == 0) {
+                       syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
+                       continue;
+               }
+               ifs.int_addr = *ifaaddr;
+               if (ifs.int_addr.sa_family != AF_INET)
+                       continue;
+               no_ipaddr = 0;
+               if (ifs.int_flags & IFF_POINTOPOINT) {
+                       if (brdaddr == 0) {
+                               syslog(LOG_ERR, "%s: (get dstaddr)",
+                                       sdl->sdl_data);
+                               continue;
+                       }
+                       if (brdaddr->sa_family == AF_UNSPEC) {
+                               lookforinterfaces = 1;
+                               continue;
+                       }
+                       ifs.int_dstaddr = *brdaddr;
+               }
+               /*
+                * already known to us?
+                * This allows multiple point-to-point links
+                * to share a source address (possibly with one
+                * other link), but assumes that there will not be
+                * multiple links with the same destination address.
+                */
+               if (ifs.int_flags & IFF_POINTOPOINT) {
+                       if (if_ifwithdstaddr(&ifs.int_dstaddr))
+                               continue;
+               } else if (if_ifwithaddr(&ifs.int_addr))
+                       continue;
+               if (ifs.int_flags & IFF_LOOPBACK) {
+                       ifs.int_flags |= IFF_PASSIVE;
+                       foundloopback = 1;
+                       loopaddr = ifs.int_addr;
+                       for (ifp = ifnet; ifp; ifp = ifp->int_next)
+                           if (ifp->int_flags & IFF_POINTOPOINT)
+                               add_ptopt_localrt(ifp);
+               }
+               if (ifs.int_flags & IFF_BROADCAST) {
+                       if (brdaddr == 0) {
+                               syslog(LOG_ERR, "%s: (get broadaddr)",
+                                       sdl->sdl_data);
+                               continue;
+                       }
+                       ifs.int_dstaddr = *brdaddr;
+               }
+               /*
+                * Use a minimum metric of one;
+                * treat the interface metric (default 0)
+                * as an increment to the hop count of one.
+                */
+               ifs.int_metric = ifam->ifam_metric + 1;
+               if (netmask == 0) {
+                               syslog(LOG_ERR, "%s: (get netmask)",
+                                       sdl->sdl_data);
+                               continue;
+               }
+               sin = (struct sockaddr_in *)netmask;
+               ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
+               sin = (struct sockaddr_in *)&ifs.int_addr;
+               i = ntohl(sin->sin_addr.s_addr);
+               if (IN_CLASSA(i))
+                       ifs.int_netmask = IN_CLASSA_NET;
+               else if (IN_CLASSB(i))
+                       ifs.int_netmask = IN_CLASSB_NET;
+               else
+                       ifs.int_netmask = IN_CLASSC_NET;
+               ifs.int_net = i & ifs.int_netmask;
+               ifs.int_subnet = i & ifs.int_subnetmask;
+               if (ifs.int_subnetmask != ifs.int_netmask)
+                       ifs.int_flags |= IFF_SUBNET;
+               ifp = (struct interface *)
+                       malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
+               if (ifp == 0) {
+                       printf("routed: out of memory\n");
+                       lookforinterfaces = 1;
+                       break;
+               }
+               *ifp = ifs;
+               /*
+                * Count the # of directly connected networks
+                * and point to point links which aren't looped
+                * back to ourself.  This is used below to
+                * decide if we should be a routing ``supplier''.
+                */
+               if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
+                   ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
+                   if_ifwithaddr(&ifs.int_dstaddr) == 0))
+                       externalinterfaces++;
+               /*
+                * If we have a point-to-point link, we want to act
+                * as a supplier even if it's our only interface,
+                * as that's the only way our peer on the other end
+                * can tell that the link is up.
+                */
+               if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
+                       supplier = 1;
+               ifp->int_name = (char *)(ifp + 1);
+               strcpy(ifp->int_name, sdl->sdl_data);
+               *ifnext = ifp;
+               ifnext = &ifp->int_next;
+               traceinit(ifp);
+               addrouteforif(ifp);
+       }
+       if (externalinterfaces > 1 && supplier < 0)
+               supplier = 1;
+       free(buf);
+}
+
+/*
+ * Add route for interface if not currently installed.
+ * Create route to other end if a point-to-point link,
+ * otherwise a route to this (sub)network.
+ * INTERNET SPECIFIC.
+ */
+addrouteforif(ifp)
+       register struct interface *ifp;
+{
+       struct sockaddr_in net;
+       struct sockaddr *dst;
+       int state;
+       register struct rt_entry *rt;
+
+       if (ifp->int_flags & IFF_POINTOPOINT)
+               dst = &ifp->int_dstaddr;
+       else {
+               memset(&net, 0, sizeof (net));
+               net.sin_family = AF_INET;
+               net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
+               dst = (struct sockaddr *)&net;
+       }
+       rt = rtfind(dst);
+       if (rt &&
+           (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
+               return;
+       if (rt)
+               rtdelete(rt);
+       /*
+        * If interface on subnetted network,
+        * install route to network as well.
+        * This is meant for external viewers.
+        */
+       if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
+               struct in_addr subnet;
+
+               subnet = net.sin_addr;
+               net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
+               rt = rtfind(dst);
+               if (rt == 0)
+                       rtadd(dst, &ifp->int_addr, ifp->int_metric,
+                           ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
+                           RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
+               else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == 
+                   (RTS_INTERNAL|RTS_SUBNET) &&
+                   ifp->int_metric < rt->rt_metric)
+                       rtchange(rt, &rt->rt_router, ifp->int_metric);
+               net.sin_addr = subnet;
+       }
+       if (ifp->int_transitions++ > 0)
+               syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
+       state = ifp->int_flags &
+           (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
+       if (ifp->int_flags & IFF_POINTOPOINT &&
+           (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
+           ifp->int_netmask) != ifp->int_net)
+               state &= ~RTS_SUBNET;
+       if (ifp->int_flags & IFF_LOOPBACK)
+               state |= RTS_EXTERNAL;
+       rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
+       if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
+               add_ptopt_localrt(ifp);
+}
+
+/*
+ * Add route to local end of point-to-point using loopback.
+ * If a route to this network is being sent to neighbors on other nets,
+ * mark this route as subnet so we don't have to propagate it too.
+ */
+add_ptopt_localrt(ifp)
+       register struct interface *ifp;
+{
+       struct rt_entry *rt;
+       struct sockaddr *dst;
+       struct sockaddr_in net;
+       int state;
+
+       state = RTS_INTERFACE | RTS_PASSIVE;
+
+       /* look for route to logical network */
+       memset(&net, 0, sizeof (net));
+       net.sin_family = AF_INET;
+       net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
+       dst = (struct sockaddr *)&net;
+       rt = rtfind(dst);
+       if (rt && rt->rt_state & RTS_INTERNAL)
+               state |= RTS_SUBNET;
+
+       dst = &ifp->int_addr;
+       if (rt = rtfind(dst)) {
+               if (rt && rt->rt_state & RTS_INTERFACE)
+                       return;
+               rtdelete(rt);
+       }
+       rtadd(dst, &loopaddr, 1, state);
+}
+
+/*
+ * As a concession to the ARPANET we read a list of gateways
+ * from /etc/gateways and add them to our tables.  This file
+ * exists at each ARPANET gateway and indicates a set of ``remote''
+ * gateways (i.e. a gateway which we can't immediately determine
+ * if it's present or not as we can do for those directly connected
+ * at the hardware level).  If a gateway is marked ``passive''
+ * in the file, then we assume it doesn't have a routing process
+ * of our design and simply assume it's always present.  Those
+ * not marked passive are treated as if they were directly
+ * connected -- they're added into the interface list so we'll
+ * send them routing updates.
+ *
+ * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
+ */
+gwkludge()
+{
+       struct sockaddr_in dst, gate;
+       FILE *fp;
+       char *type, *dname, *gname, *qual, buf[BUFSIZ];
+       struct interface *ifp;
+       int metric, n;
+       struct rt_entry route;
+
+       fp = fopen(_PATH_GATEWAYS, "r");
+       if (fp == NULL)
+               return;
+       qual = buf;
+       dname = buf + 64;
+       gname = buf + ((BUFSIZ - 64) / 3);
+       type = buf + (((BUFSIZ - 64) * 2) / 3);
+       memset(&dst, 0, sizeof (dst));
+       memset(&gate, 0, sizeof (gate));
+       memset(&route, 0, sizeof(route));
+/* format: {net | host} XX gateway XX metric DD [passive | external]\n */
+#define        readentry(fp) \
+       fscanf((fp), "%s %s gateway %s metric %d %s\n", \
+               type, dname, gname, &metric, qual)
+       for (;;) {
+               if ((n = readentry(fp)) == EOF)
+                       break;
+               if (!getnetorhostname(type, dname, &dst))
+                       continue;
+               if (!gethostnameornumber(gname, &gate))
+                       continue;
+               if (metric == 0)                        /* XXX */
+                       metric = 1;
+               if (strcmp(qual, "passive") == 0) {
+                       /*
+                        * Passive entries aren't placed in our tables,
+                        * only the kernel's, so we don't copy all of the
+                        * external routing information within a net.
+                        * Internal machines should use the default
+                        * route to a suitable gateway (like us).
+                        */
+                       route.rt_dst = *(struct sockaddr *) &dst;
+                       route.rt_router = *(struct sockaddr *) &gate;
+                       route.rt_flags = RTF_UP;
+                       if (strcmp(type, "host") == 0)
+                               route.rt_flags |= RTF_HOST;
+                       if (metric)
+                               route.rt_flags |= RTF_GATEWAY;
+                       (void) rtioctl(ADD, &route.rt_rt);
+                       continue;
+               }
+               if (strcmp(qual, "external") == 0) {
+                       /*
+                        * Entries marked external are handled
+                        * by other means, e.g. EGP,
+                        * and are placed in our tables only
+                        * to prevent overriding them
+                        * with something else.
+                        */
+                       rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
+                       continue;
+               }
+               /* assume no duplicate entries */
+               externalinterfaces++;
+               ifp = (struct interface *)malloc(sizeof (*ifp));
+               memset(ifp, 0, sizeof (*ifp));
+               ifp->int_flags = IFF_REMOTE;
+               /* can't identify broadcast capability */
+               ifp->int_net = inet_netof(dst.sin_addr);
+               if (strcmp(type, "host") == 0) {
+                       ifp->int_flags |= IFF_POINTOPOINT;
+                       ifp->int_dstaddr = *((struct sockaddr *)&dst);
+               }
+               ifp->int_addr = *((struct sockaddr *)&gate);
+               ifp->int_metric = metric;
+               ifp->int_next = ifnet;
+               ifnet = ifp;
+               addrouteforif(ifp);
+       }
+       fclose(fp);
+}
+
+getnetorhostname(type, name, sin)
+       char *type, *name;
+       struct sockaddr_in *sin;
+{
+
+       if (strcmp(type, "net") == 0) {
+               struct netent *np = getnetbyname(name);
+               int n;
+
+               if (np == 0)
+                       n = inet_network(name);
+               else {
+                       if (np->n_addrtype != AF_INET)
+                               return (0);
+                       n = np->n_net;
+                       /*
+                        * getnetbyname returns right-adjusted value.
+                        */
+                       if (n < 128)
+                               n <<= IN_CLASSA_NSHIFT;
+                       else if (n < 65536)
+                               n <<= IN_CLASSB_NSHIFT;
+                       else
+                               n <<= IN_CLASSC_NSHIFT;
+               }
+               sin->sin_family = AF_INET;
+               sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
+               return (1);
+       }
+       if (strcmp(type, "host") == 0) {
+               struct hostent *hp = gethostbyname(name);
+
+               if (hp == 0)
+                       sin->sin_addr.s_addr = inet_addr(name);
+               else {
+                       if (hp->h_addrtype != AF_INET)
+                               return (0);
+                       memmove(&sin->sin_addr, hp->h_addr, hp->h_length);
+               }
+               sin->sin_family = AF_INET;
+               return (1);
+       }
+       return (0);
+}
+
+gethostnameornumber(name, sin)
+       char *name;
+       struct sockaddr_in *sin;
+{
+       struct hostent *hp;
+
+       hp = gethostbyname(name);
+       if (hp) {
+               memmove(&sin->sin_addr, hp->h_addr, hp->h_length);
+               sin->sin_family = hp->h_addrtype;
+               return (1);
+       }
+       sin->sin_addr.s_addr = inet_addr(name);
+       sin->sin_family = AF_INET;
+       return (sin->sin_addr.s_addr != -1);
+}
diff --git a/routed.tproj/table.h b/routed.tproj/table.h
new file mode 100644 (file)
index 0000000..3e0246d
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * Routing table structure; differs a bit from kernel tables.
+ *
+ * Note: the union below must agree in the first 4 members
+ * so the ioctl's will work.
+ */
+struct rthash {
+       struct  rt_entry *rt_forw;
+       struct  rt_entry *rt_back;
+};
+#ifdef RTM_ADD
+#define rtentry ortentry
+#endif
+
+struct rt_entry {
+       struct  rt_entry *rt_forw;
+       struct  rt_entry *rt_back;
+       union {
+               struct  rtentry rtu_rt;
+               struct rtuentry {
+                       u_long  rtu_hash;
+                       struct  sockaddr rtu_dst;
+                       struct  sockaddr rtu_router;
+                       short   rtu_rtflags; /* used by rtioctl */
+                       short   rtu_wasted[5];
+                       int     rtu_flags;
+                       int     rtu_state;
+                       int     rtu_timer;
+                       int     rtu_metric;
+                       int     rtu_ifmetric;
+                       struct  interface *rtu_ifp;
+               } rtu_entry;
+       } rt_rtu;
+};
+
+#define        rt_rt           rt_rtu.rtu_entry                /* pass to ioctl */
+#define        rt_hash         rt_rtu.rtu_entry.rtu_hash       /* for net or host */
+#define        rt_dst          rt_rtu.rtu_entry.rtu_dst        /* match value */
+#define        rt_router       rt_rtu.rtu_entry.rtu_router     /* who to forward to */
+#define        rt_flags        rt_rtu.rtu_entry.rtu_flags      /* kernel flags */
+#define        rt_timer        rt_rtu.rtu_entry.rtu_timer      /* for invalidation */
+#define        rt_state        rt_rtu.rtu_entry.rtu_state      /* see below */
+#define        rt_metric       rt_rtu.rtu_entry.rtu_metric     /* cost of route */
+#define        rt_ifmetric     rt_rtu.rtu_entry.rtu_ifmetric   /* cost of route if */
+#define        rt_ifp          rt_rtu.rtu_entry.rtu_ifp        /* interface to take */
+
+#define        ROUTEHASHSIZ    32              /* must be a power of 2 */
+#define        ROUTEHASHMASK   (ROUTEHASHSIZ - 1)
+
+/*
+ * "State" of routing table entry.
+ */
+#define        RTS_CHANGED     0x1             /* route has been altered recently */
+#define        RTS_EXTERNAL    0x2             /* extern info, not installed or sent */
+#define        RTS_INTERNAL    0x4             /* internal route, not installed */
+#define        RTS_PASSIVE     IFF_PASSIVE     /* don't time out route */
+#define        RTS_INTERFACE   IFF_INTERFACE   /* route is for network interface */
+#define        RTS_REMOTE      IFF_REMOTE      /* route is for ``remote'' entity */
+#define        RTS_SUBNET      IFF_SUBNET      /* route is for network subnet */
+
+/*
+ * Flags are same as kernel, with this addition for af_rtflags:
+ */
+#define        RTF_SUBNET      0x80000         /* pseudo: route to subnet */
+
+EXTERN struct  rthash nethash[ROUTEHASHSIZ];
+EXTERN struct  rthash hosthash[ROUTEHASHSIZ];
+struct rt_entry *rtlookup();
+struct rt_entry *rtfind();
diff --git a/routed.tproj/tables.c b/routed.tproj/tables.c
new file mode 100644 (file)
index 0000000..f9ade65
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/syslog.h>
+
+#ifndef DEBUG
+#define        DEBUG   0
+#endif
+
+#ifdef RTM_ADD
+#define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);}
+#else
+#define FIXLEN(s) { }
+#endif
+
+int    install = !DEBUG;               /* if 1 call kernel */
+
+/*
+ * Lookup dst in the tables for an exact match.
+ */
+struct rt_entry *
+rtlookup(dst)
+       struct sockaddr *dst;
+{
+       register struct rt_entry *rt;
+       register struct rthash *rh;
+       register u_int hash;
+       struct afhash h;
+       int doinghost = 1;
+
+       if (dst->sa_family >= af_max)
+               return (0);
+       (*afswitch[dst->sa_family].af_hash)(dst, &h);
+       hash = h.afh_hosthash;
+       rh = &hosthash[hash & ROUTEHASHMASK];
+again:
+       for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+               if (rt->rt_hash != hash)
+                       continue;
+               if (equal(&rt->rt_dst, dst))
+                       return (rt);
+       }
+       if (doinghost) {
+               doinghost = 0;
+               hash = h.afh_nethash;
+               rh = &nethash[hash & ROUTEHASHMASK];
+               goto again;
+       }
+       return (0);
+}
+
+struct sockaddr wildcard;      /* zero valued cookie for wildcard searches */
+
+/*
+ * Find a route to dst as the kernel would.
+ */
+struct rt_entry *
+rtfind(dst)
+       struct sockaddr *dst;
+{
+       register struct rt_entry *rt;
+       register struct rthash *rh;
+       register u_int hash;
+       struct afhash h;
+       int af = dst->sa_family;
+       int doinghost = 1, (*match)();
+
+       if (af >= af_max)
+               return (0);
+       (*afswitch[af].af_hash)(dst, &h);
+       hash = h.afh_hosthash;
+       rh = &hosthash[hash & ROUTEHASHMASK];
+
+again:
+       for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+               if (rt->rt_hash != hash)
+                       continue;
+               if (doinghost) {
+                       if (equal(&rt->rt_dst, dst))
+                               return (rt);
+               } else {
+                       if (rt->rt_dst.sa_family == af &&
+                           (*match)(&rt->rt_dst, dst))
+                               return (rt);
+               }
+       }
+       if (doinghost) {
+               doinghost = 0;
+               hash = h.afh_nethash;
+               rh = &nethash[hash & ROUTEHASHMASK];
+               match = afswitch[af].af_netmatch;
+               goto again;
+       }
+#ifdef notyet
+       /*
+        * Check for wildcard gateway, by convention network 0.
+        */
+       if (dst != &wildcard) {
+               dst = &wildcard, hash = 0;
+               goto again;
+       }
+#endif
+       return (0);
+}
+
+rtadd(dst, gate, metric, state)
+       struct sockaddr *dst, *gate;
+       int metric, state;
+{
+       struct afhash h;
+       register struct rt_entry *rt;
+       struct rthash *rh;
+       int af = dst->sa_family, flags;
+       u_int hash;
+
+       if (af >= af_max)
+               return;
+       (*afswitch[af].af_hash)(dst, &h);
+       flags = (*afswitch[af].af_rtflags)(dst);
+       /*
+        * Subnet flag isn't visible to kernel, move to state.  XXX
+        */
+       FIXLEN(dst);
+       FIXLEN(gate);
+       if (flags & RTF_SUBNET) {
+               state |= RTS_SUBNET;
+               flags &= ~RTF_SUBNET;
+       }
+       if (flags & RTF_HOST) {
+               hash = h.afh_hosthash;
+               rh = &hosthash[hash & ROUTEHASHMASK];
+       } else {
+               hash = h.afh_nethash;
+               rh = &nethash[hash & ROUTEHASHMASK];
+       }
+       rt = (struct rt_entry *)malloc(sizeof (*rt));
+       if (rt == 0)
+               return;
+       rt->rt_hash = hash;
+       rt->rt_dst = *dst;
+       rt->rt_router = *gate;
+       rt->rt_timer = 0;
+       rt->rt_flags = RTF_UP | flags;
+       rt->rt_state = state | RTS_CHANGED;
+       rt->rt_ifp = if_ifwithdstaddr(&rt->rt_dst);
+       if (rt->rt_ifp == 0)
+               rt->rt_ifp = if_ifwithnet(&rt->rt_router);
+       if ((state & RTS_INTERFACE) == 0)
+               rt->rt_flags |= RTF_GATEWAY;
+       rt->rt_metric = metric;
+       insque(rt, rh);
+       TRACE_ACTION("ADD", rt);
+       /*
+        * If the ioctl fails because the gateway is unreachable
+        * from this host, discard the entry.  This should only
+        * occur because of an incorrect entry in /etc/gateways.
+        */
+       if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
+           rtioctl(ADD, &rt->rt_rt) < 0) {
+               if (errno != EEXIST && gate->sa_family < af_max)
+                       syslog(LOG_ERR,
+                       "adding route to net/host %s through gateway %s: %m\n",
+                          (*afswitch[dst->sa_family].af_format)(dst),
+                          (*afswitch[gate->sa_family].af_format)(gate));
+               perror("ADD ROUTE");
+               if (errno == ENETUNREACH) {
+                       TRACE_ACTION("DELETE", rt);
+                       remque(rt);
+                       free((char *)rt);
+               }
+       }
+}
+
+rtchange(rt, gate, metric)
+       struct rt_entry *rt;
+       struct sockaddr *gate;
+       short metric;
+{
+       int add = 0, delete = 0, newgateway = 0;
+       struct rtuentry oldroute;
+
+       FIXLEN(gate);
+       FIXLEN(&(rt->rt_router));
+       FIXLEN(&(rt->rt_dst));
+       if (!equal(&rt->rt_router, gate)) {
+               newgateway++;
+               TRACE_ACTION("CHANGE FROM ", rt);
+       } else if (metric != rt->rt_metric)
+               TRACE_NEWMETRIC(rt, metric);
+       if ((rt->rt_state & RTS_INTERNAL) == 0) {
+               /*
+                * If changing to different router, we need to add
+                * new route and delete old one if in the kernel.
+                * If the router is the same, we need to delete
+                * the route if has become unreachable, or re-add
+                * it if it had been unreachable.
+                */
+               if (newgateway) {
+                       add++;
+                       if (rt->rt_metric != HOPCNT_INFINITY)
+                               delete++;
+               } else if (metric == HOPCNT_INFINITY)
+                       delete++;
+               else if (rt->rt_metric == HOPCNT_INFINITY)
+                       add++;
+       }
+       if (delete)
+               oldroute = rt->rt_rt;
+       if ((rt->rt_state & RTS_INTERFACE) && delete) {
+               rt->rt_state &= ~RTS_INTERFACE;
+               rt->rt_flags |= RTF_GATEWAY;
+               if (metric > rt->rt_metric && delete)
+                       syslog(LOG_ERR, "%s route to interface %s (timed out)",
+                           add? "changing" : "deleting",
+                           rt->rt_ifp ? rt->rt_ifp->int_name : "?");
+       }
+       if (add) {
+               rt->rt_router = *gate;
+               rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
+               if (rt->rt_ifp == 0)
+                       rt->rt_ifp = if_ifwithnet(&rt->rt_router);
+       }
+       rt->rt_metric = metric;
+       rt->rt_state |= RTS_CHANGED;
+       if (newgateway)
+               TRACE_ACTION("CHANGE TO   ", rt);
+#ifndef RTM_ADD
+       if (add && rtioctl(ADD, &rt->rt_rt) < 0)
+               perror("ADD ROUTE");
+       if (delete && rtioctl(DELETE, &oldroute) < 0)
+               perror("DELETE ROUTE");
+#else
+       if (delete && !add) {
+               if (rtioctl(DELETE, &oldroute) < 0)
+                       perror("DELETE ROUTE");
+       } else if (!delete && add) {
+               if (rtioctl(ADD, &rt->rt_rt) < 0)
+                       perror("ADD ROUTE");
+       } else if (delete && add) {
+               if (rtioctl(CHANGE, &rt->rt_rt) < 0)
+                       perror("CHANGE ROUTE");
+       }
+#endif
+}
+
+rtdelete(rt)
+       struct rt_entry *rt;
+{
+
+       TRACE_ACTION("DELETE", rt);
+       FIXLEN(&(rt->rt_router));
+       FIXLEN(&(rt->rt_dst));
+       if (rt->rt_metric < HOPCNT_INFINITY) {
+           if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE)
+               syslog(LOG_ERR,
+                   "deleting route to interface %s? (timed out?)",
+                   rt->rt_ifp->int_name);
+           if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
+                                           rtioctl(DELETE, &rt->rt_rt) < 0)
+                   perror("rtdelete");
+       }
+       remque(rt);
+       free((char *)rt);
+}
+
+rtdeleteall(sig)
+       int sig;
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1;
+
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+               rt = rh->rt_forw;
+               for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+                       if (rt->rt_state & RTS_INTERFACE ||
+                           rt->rt_metric >= HOPCNT_INFINITY)
+                               continue;
+                       TRACE_ACTION("DELETE", rt);
+                       if ((rt->rt_state & (RTS_INTERNAL|RTS_EXTERNAL)) == 0 &&
+                           rtioctl(DELETE, &rt->rt_rt) < 0)
+                               perror("rtdeleteall");
+               }
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       exit(sig);
+}
+
+/*
+ * If we have an interface to the wide, wide world,
+ * add an entry for an Internet default route (wildcard) to the internal
+ * tables and advertise it.  This route is not added to the kernel routes,
+ * but this entry prevents us from listening to other people's defaults
+ * and installing them in the kernel here.
+ */
+rtdefault()
+{
+       extern struct sockaddr inet_default;
+
+       rtadd(&inet_default, &inet_default, 1,
+               RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL);
+}
+
+rtinit()
+{
+       register struct rthash *rh;
+
+       for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
+               rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
+       for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
+               rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
+}
+
+rtioctl(action, ort)
+       int action;
+       struct rtuentry *ort;
+{
+#ifndef RTM_ADD
+       if (install == 0)
+               return (errno = 0);
+       ort->rtu_rtflags = ort->rtu_flags;
+       switch (action) {
+
+       case ADD:
+               return (ioctl(s, SIOCADDRT, (char *)ort));
+
+       case DELETE:
+               return (ioctl(s, SIOCDELRT, (char *)ort));
+
+       default:
+               return (-1);
+       }
+#else /* RTM_ADD */
+       struct {
+               struct rt_msghdr w_rtm;
+               struct sockaddr_in w_dst;
+               struct sockaddr w_gate;
+               struct sockaddr_in w_netmask;
+       } w;
+#define rtm w.w_rtm
+
+       memset(&w, 0, sizeof(w));
+       rtm.rtm_msglen = sizeof(w);
+       rtm.rtm_version = RTM_VERSION;
+       rtm.rtm_type = (action == ADD ? RTM_ADD :
+                               (action == DELETE ? RTM_DELETE : RTM_CHANGE));
+#undef rt_dst
+       rtm.rtm_flags = ort->rtu_flags;
+       rtm.rtm_seq = ++seqno;
+       rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
+       memmove(&w.w_dst, &ort->rtu_dst, sizeof(w.w_dst));
+       memmove(&w.w_gate, &ort->rtu_router, sizeof(w.w_gate));
+       w.w_dst.sin_family = AF_INET;
+       w.w_dst.sin_len = sizeof(w.w_dst);
+       w.w_gate.sa_family = AF_INET;
+       w.w_gate.sa_len = sizeof(w.w_gate);
+       if (rtm.rtm_flags & RTF_HOST) {
+               rtm.rtm_msglen -= sizeof(w.w_netmask);
+       } else {
+               register char *cp;
+               int len;
+
+               rtm.rtm_addrs |= RTA_NETMASK;
+               w.w_netmask.sin_addr.s_addr =
+                       inet_maskof(w.w_dst.sin_addr.s_addr);
+               for (cp = (char *)(1 + &w.w_netmask.sin_addr);
+                                   --cp > (char *) &w.w_netmask; )
+                       if (*cp)
+                               break;
+               len = cp - (char *)&w.w_netmask;
+               if (len) {
+                       len++;
+                       w.w_netmask.sin_len = len;
+                       len = 1 + ((len - 1) | (sizeof(long) - 1));
+               } else 
+                       len = sizeof(long);
+               rtm.rtm_msglen -= (sizeof(w.w_netmask) - len);
+       }
+       errno = 0;
+       return (install ? write(r, (char *)&w, rtm.rtm_msglen) : (errno = 0));
+#endif  /* RTM_ADD */
+}
diff --git a/routed.tproj/timer.c b/routed.tproj/timer.c
new file mode 100644 (file)
index 0000000..cf8e3ba
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "defs.h"
+
+int    faketime;
+
+/*
+ * Timer routine.  Performs routing information supply
+ * duties and manages timers on routing table entries.
+ * Management of the RTS_CHANGED bit assumes that we broadcast
+ * each time called.
+ */
+void
+timer()
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1, timetobroadcast;
+       extern int externalinterfaces;
+
+       (void) gettimeofday(&now, (struct timezone *)NULL);
+       faketime += TIMER_RATE;
+       if (lookforinterfaces && (faketime % CHECK_INTERVAL) == 0)
+               ifinit();
+       timetobroadcast = supplier && (faketime % SUPPLY_INTERVAL) == 0;
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+               rt = rh->rt_forw;
+               for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+                       /*
+                        * We don't advance time on a routing entry for
+                        * a passive gateway, or any interface if we're
+                        * not acting as supplier.
+                        */
+                       if (!(rt->rt_state & RTS_PASSIVE) &&
+                           (supplier || !(rt->rt_state & RTS_INTERFACE)))
+                               rt->rt_timer += TIMER_RATE;
+                       if (rt->rt_timer >= GARBAGE_TIME) {
+                               rt = rt->rt_back;
+                               rtdelete(rt->rt_forw);
+                               continue;
+                       }
+                       if (rt->rt_timer >= EXPIRE_TIME &&
+                           rt->rt_metric < HOPCNT_INFINITY)
+                               rtchange(rt, &rt->rt_router, HOPCNT_INFINITY);
+                       rt->rt_state &= ~RTS_CHANGED;
+               }
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       if (timetobroadcast) {
+               toall(supply, 0, (struct interface *)NULL);
+               lastbcast = now;
+               lastfullupdate = now;
+               needupdate = 0;         /* cancel any pending dynamic update */
+               nextbcast.tv_sec = 0;
+       }
+}
+
+/*
+ * On hangup, let everyone know we're going away.
+ */
+hup()
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1;
+
+       if (supplier) {
+again:
+               for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+                       rt = rh->rt_forw;
+                       for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
+                               rt->rt_metric = HOPCNT_INFINITY;
+               }
+               if (doinghost) {
+                       doinghost = 0;
+                       base = nethash;
+                       goto again;
+               }
+               toall(supply, 0, (struct interface *)NULL);
+       }
+       exit(1);
+}
diff --git a/routed.tproj/trace.c b/routed.tproj/trace.c
new file mode 100644 (file)
index 0000000..8695cf9
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+
+/*
+ * Routing Table Management Daemon
+ */
+#define        RIPCMDS
+#include "defs.h"
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "pathnames.h"
+
+#define        NRECORDS        50              /* size of circular trace buffer */
+#ifdef DEBUG
+FILE   *ftrace = stdout;
+int    traceactions = 0;
+#endif
+static struct timeval lastlog;
+static char *savetracename;
+
+traceinit(ifp)
+       register struct interface *ifp;
+{
+       static int iftraceinit();
+
+       if (iftraceinit(ifp, &ifp->int_input) &&
+           iftraceinit(ifp, &ifp->int_output))
+               return;
+       tracehistory = 0;
+       fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
+}
+
+static
+iftraceinit(ifp, ifd)
+       struct interface *ifp;
+       register struct ifdebug *ifd;
+{
+       register struct iftrace *t;
+
+       ifd->ifd_records =
+         (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
+       if (ifd->ifd_records == 0)
+               return (0);
+       ifd->ifd_front = ifd->ifd_records;
+       ifd->ifd_count = 0;
+       for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
+               t->ift_size = 0;
+               t->ift_packet = 0;
+       }
+       ifd->ifd_if = ifp;
+       return (1);
+}
+
+traceon(file)
+       char *file;
+{
+       struct stat stbuf;
+
+       if (ftrace != NULL)
+               return;
+       if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
+               return;
+       savetracename = file;
+       (void) gettimeofday(&now, (struct timezone *)NULL);
+       ftrace = fopen(file, "a");
+       if (ftrace == NULL)
+               return;
+       dup2(fileno(ftrace), 1);
+       dup2(fileno(ftrace), 2);
+       traceactions = 1;
+       fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
+}
+
+traceoff()
+{
+       if (!traceactions)
+               return;
+       if (ftrace != NULL) {
+               int fd = open(_PATH_DEVNULL, O_RDWR);
+
+               fprintf(ftrace, "Tracing disabled %s\n",
+                   ctime((time_t *)&now.tv_sec));
+               fflush(ftrace);
+               (void) dup2(fd, 1);
+               (void) dup2(fd, 2);
+               (void) close(fd);
+               fclose(ftrace);
+               ftrace = NULL;
+       }
+       traceactions = 0;
+       tracehistory = 0;
+       tracepackets = 0;
+       tracecontents = 0;
+}
+
+void
+sigtrace(s)
+       int s;
+{
+
+       if (s == SIGUSR2)
+               traceoff();
+       else if (ftrace == NULL && savetracename)
+               traceon(savetracename);
+       else
+               bumploglevel();
+}
+
+/*
+ * Move to next higher level of tracing when -t option processed or
+ * SIGUSR1 is received.  Successive levels are:
+ *     traceactions
+ *     traceactions + tracepackets
+ *     traceactions + tracehistory (packets and contents after change)
+ *     traceactions + tracepackets + tracecontents
+ */
+bumploglevel()
+{
+
+       (void) gettimeofday(&now, (struct timezone *)NULL);
+       if (traceactions == 0) {
+               traceactions++;
+               if (ftrace)
+                       fprintf(ftrace, "Tracing actions started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       } else if (tracepackets == 0) {
+               tracepackets++;
+               tracehistory = 0;
+               tracecontents = 0;
+               if (ftrace)
+                       fprintf(ftrace, "Tracing packets started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       } else if (tracehistory == 0) {
+               tracehistory++;
+               if (ftrace)
+                       fprintf(ftrace, "Tracing history started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       } else {
+               tracepackets++;
+               tracecontents++;
+               tracehistory = 0;
+               if (ftrace)
+                       fprintf(ftrace, "Tracing packet contents started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       }
+       if (ftrace)
+               fflush(ftrace);
+}
+
+trace(ifd, who, p, len, m)
+       register struct ifdebug *ifd;
+       struct sockaddr *who;
+       char *p;
+       int len, m;
+{
+       register struct iftrace *t;
+
+       if (ifd->ifd_records == 0)
+               return;
+       t = ifd->ifd_front++;
+       if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
+               ifd->ifd_front = ifd->ifd_records;
+       if (ifd->ifd_count < NRECORDS)
+               ifd->ifd_count++;
+       if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
+               free(t->ift_packet);
+               t->ift_packet = 0;
+       }
+       t->ift_stamp = now;
+       t->ift_who = *who;
+       if (len > 0 && t->ift_packet == 0) {
+               t->ift_packet = malloc(len);
+               if (t->ift_packet == 0)
+                       len = 0;
+       }
+       if (len > 0)
+               memmove(t->ift_packet, p, len);
+       t->ift_size = len;
+       t->ift_metric = m;
+}
+
+traceaction(fd, action, rt)
+       FILE *fd;
+       char *action;
+       struct rt_entry *rt;
+{
+       struct sockaddr_in *dst, *gate;
+       static struct bits {
+               int     t_bits;
+               char    *t_name;
+       } flagbits[] = {
+               { RTF_UP,       "UP" },
+               { RTF_GATEWAY,  "GATEWAY" },
+               { RTF_HOST,     "HOST" },
+               { 0 }
+       }, statebits[] = {
+               { RTS_PASSIVE,  "PASSIVE" },
+               { RTS_REMOTE,   "REMOTE" },
+               { RTS_INTERFACE,"INTERFACE" },
+               { RTS_CHANGED,  "CHANGED" },
+               { RTS_INTERNAL, "INTERNAL" },
+               { RTS_EXTERNAL, "EXTERNAL" },
+               { RTS_SUBNET,   "SUBNET" },
+               { 0 }
+       };
+       register struct bits *p;
+       register int first;
+       char *cp;
+       struct interface *ifp;
+
+       if (fd == NULL)
+               return;
+       if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
+               fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
+               lastlog = now;
+       }
+       fprintf(fd, "%s ", action);
+       dst = (struct sockaddr_in *)&rt->rt_dst;
+       gate = (struct sockaddr_in *)&rt->rt_router;
+       fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
+       fprintf(fd, "router %s, metric %d, flags",
+            inet_ntoa(gate->sin_addr), rt->rt_metric);
+       cp = " %s";
+       for (first = 1, p = flagbits; p->t_bits > 0; p++) {
+               if ((rt->rt_flags & p->t_bits) == 0)
+                       continue;
+               fprintf(fd, cp, p->t_name);
+               if (first) {
+                       cp = "|%s";
+                       first = 0;
+               }
+       }
+       fprintf(fd, " state");
+       cp = " %s";
+       for (first = 1, p = statebits; p->t_bits > 0; p++) {
+               if ((rt->rt_state & p->t_bits) == 0)
+                       continue;
+               fprintf(fd, cp, p->t_name);
+               if (first) {
+                       cp = "|%s";
+                       first = 0;
+               }
+       }
+       fprintf(fd, " timer %d\n", rt->rt_timer);
+       if (tracehistory && !tracepackets &&
+           (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
+               dumpif(fd, rt->rt_ifp);
+       fflush(fd);
+       if (ferror(fd))
+               traceoff();
+}
+
+tracenewmetric(fd, rt, newmetric)
+       FILE *fd;
+       struct rt_entry *rt;
+       int newmetric;
+{
+       struct sockaddr_in *dst, *gate;
+
+       if (fd == NULL)
+               return;
+       if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
+               fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
+               lastlog = now;
+       }
+       dst = (struct sockaddr_in *)&rt->rt_dst;
+       gate = (struct sockaddr_in *)&rt->rt_router;
+       fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
+       fprintf(fd, "router %s, from %d to %d\n",
+            inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
+       fflush(fd);
+       if (ferror(fd))
+               traceoff();
+}
+
+dumpif(fd, ifp)
+       FILE *fd;
+       register struct interface *ifp;
+{
+       if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
+               fprintf(fd, "*** Packet history for interface %s ***\n",
+                       ifp->int_name);
+#ifdef notneeded
+               dumptrace(fd, "to", &ifp->int_output);
+#endif
+               dumptrace(fd, "from", &ifp->int_input);
+               fprintf(fd, "*** end packet history ***\n");
+       }
+}
+
+dumptrace(fd, dir, ifd)
+       FILE *fd;
+       char *dir;
+       register struct ifdebug *ifd;
+{
+       register struct iftrace *t;
+       char *cp = !strcmp(dir, "to") ? "Output" : "Input";
+
+       if (ifd->ifd_front == ifd->ifd_records &&
+           ifd->ifd_front->ift_size == 0) {
+               fprintf(fd, "%s: no packets.\n", cp);
+               fflush(fd);
+               return;
+       }
+       fprintf(fd, "%s trace:\n", cp);
+       t = ifd->ifd_front - ifd->ifd_count;
+       if (t < ifd->ifd_records)
+               t += NRECORDS;
+       for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
+               if (t >= ifd->ifd_records + NRECORDS)
+                       t = ifd->ifd_records;
+               if (t->ift_size == 0)
+                       continue;
+               dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
+                   &t->ift_stamp);
+       }
+}
+
+dumppacket(fd, dir, who, cp, size, stamp)
+       FILE *fd;
+       struct sockaddr_in *who;                /* should be sockaddr */
+       char *dir, *cp;
+       register int size;
+       struct timeval *stamp;
+{
+       register struct rip *msg = (struct rip *)cp;
+       register struct netinfo *n;
+
+       if (fd == NULL)
+               return;
+       if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
+               fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
+                   dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
+                   ctime((time_t *)&stamp->tv_sec));
+       else {
+               fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
+                   dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
+               fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
+                   ctime((time_t *)&stamp->tv_sec));
+               fflush(fd);
+               return;
+       }
+       if (tracepackets && tracecontents == 0) {
+               fflush(fd);
+               return;
+       }
+       switch (msg->rip_cmd) {
+
+       case RIPCMD_REQUEST:
+       case RIPCMD_RESPONSE:
+               size -= 4 * sizeof (char);
+               n = msg->rip_nets;
+               for (; size > 0; n++, size -= sizeof (struct netinfo)) {
+                       if (size < sizeof (struct netinfo)) {
+                               fprintf(fd, "(truncated record, len %d)\n",
+                                   size);
+                               break;
+                       }
+                       if (sizeof(n->rip_dst.sa_family) > 1)
+                           n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
+
+                       switch ((int)n->rip_dst.sa_family) {
+
+                       case AF_INET:
+                               fprintf(fd, "\tdst %s metric %d\n",
+#define        satosin(sa)     ((struct sockaddr_in *)&sa)
+                                    inet_ntoa(satosin(n->rip_dst)->sin_addr),
+                                    ntohl(n->rip_metric));
+                               break;
+
+                       default:
+                               fprintf(fd, "\taf %d? metric %d\n",
+                                    n->rip_dst.sa_family,
+                                    ntohl(n->rip_metric));
+                               break;
+                       }
+               }
+               break;
+
+       case RIPCMD_TRACEON:
+               fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
+               break;
+
+       case RIPCMD_TRACEOFF:
+               break;
+       }
+       fflush(fd);
+       if (ferror(fd))
+               traceoff();
+}
diff --git a/routed.tproj/trace.h b/routed.tproj/trace.h
new file mode 100644 (file)
index 0000000..aa7f753
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/5/93
+ */
+
+/*
+ * Routing table management daemon.
+ */
+
+/*
+ * Trace record format.
+ */
+struct iftrace {
+       struct  timeval ift_stamp;      /* time stamp */
+       struct  sockaddr ift_who;       /* from/to */
+       char    *ift_packet;            /* pointer to packet */
+       short   ift_size;               /* size of packet */
+       short   ift_metric;             /* metric on associated metric */
+};
+
+/*
+ * Per interface packet tracing buffers.  An incoming and
+ * outgoing circular buffer of packets is maintained, per
+ * interface, for debugging.  Buffers are dumped whenever
+ * an interface is marked down.
+ */
+struct ifdebug {
+       struct  iftrace *ifd_records;   /* array of trace records */
+       struct  iftrace *ifd_front;     /* next empty trace record */
+       int     ifd_count;              /* number of unprinted records */
+       struct  interface *ifd_if;      /* for locating stuff */
+};
+
+/*
+ * Packet tracing stuff.
+ */
+EXTERN int     tracepackets;           /* watch packets as they go by */
+EXTERN int     tracecontents;          /* watch packet contents as they go by */
+EXTERN int     traceactions;           /* on/off */
+EXTERN int     tracehistory;           /* on/off */
+EXTERN FILE    *ftrace;                /* output trace file */
+
+#define        TRACE_ACTION(action, route) { \
+         if (traceactions) \
+               traceaction(ftrace, action, route); \
+       }
+#define        TRACE_NEWMETRIC(route, newmetric) { \
+         if (traceactions) \
+               tracenewmetric(ftrace, route, newmetric); \
+       }
+#define        TRACE_INPUT(ifp, src, pack, size) { \
+         if (tracehistory) { \
+               ifp = if_iflookup(src); \
+               if (ifp) \
+                       trace(&ifp->int_input, src, pack, size, \
+                               ntohl(ifp->int_metric)); \
+         } \
+         if (tracepackets) \
+               dumppacket(ftrace, "from", src, pack, size, &now); \
+       }
+#define        TRACE_OUTPUT(ifp, dst, size) { \
+         if (tracehistory && ifp) \
+               trace(&ifp->int_output, dst, packet, size, ifp->int_metric); \
+         if (tracepackets) \
+               dumppacket(ftrace, "to", dst, packet, size, &now); \
+       }
diff --git a/rpc_yppasswdd.tproj/Makefile b/rpc_yppasswdd.tproj/Makefile
new file mode 100644 (file)
index 0000000..9c1a49e
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rpc.yppasswdd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = yppasswd.h
+
+CFILES = passwd.c rpc.yppasswdd.c yppasswdd_mkpw.c yppasswdd_proc.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
+            rpc.yppasswdd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rpc_yppasswdd.tproj/Makefile.postamble b/rpc_yppasswdd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/rpc_yppasswdd.tproj/Makefile.preamble b/rpc_yppasswdd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/rpc_yppasswdd.tproj/PB.project b/rpc_yppasswdd.tproj/PB.project
new file mode 100644 (file)
index 0000000..4e3a617
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (yppasswd.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (passwd.c, rpc.yppasswdd.c, yppasswdd_mkpw.c, yppasswdd_proc.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rpc.yppasswdd.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rpc.yppasswdd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rpc_yppasswdd.tproj/passwd.c b/rpc_yppasswdd.tproj/passwd.c
new file mode 100644 (file)
index 0000000..a5d9982
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $      */
+
+/*
+ * Copyright (c) 1987, 1993, 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
+#include <limits.h>
+#include <util.h>
+
+static void    pw_cont __P((int sig));
+static int     pw_equal __P((char *buf, struct passwd *old_pw));
+
+int
+pw_lock(retries)
+       int retries;
+{
+       int i, fd;
+       mode_t old_mode;
+
+       /* Acquire the lock file. */
+       old_mode = umask(0);
+       fd = open(_PATH_MASTERPASSWD_LOCK, O_WRONLY|O_CREAT|O_EXCL, 0600);
+       for (i = 0; i < retries && fd < 0 && errno == EEXIST; i++) {
+               sleep(1);
+               fd = open(_PATH_MASTERPASSWD_LOCK, O_WRONLY|O_CREAT|O_EXCL,
+                         0600);
+       }
+       umask(old_mode);
+       return(fd);
+}
+
+int
+pw_mkdb()
+{
+       int pstat;
+       pid_t pid;
+       struct stat sb;
+
+       /* A zero length passwd file is never ok */
+       if (stat(_PATH_MASTERPASSWD_LOCK, &sb) == 0) {
+               if (sb.st_size == 0) {
+                       warnx("%s is zero length", _PATH_MASTERPASSWD_LOCK);
+                       return (-1);
+               }
+       }
+
+       pid = vfork();
+       if (pid == 0) {
+               execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
+                     _PATH_MASTERPASSWD_LOCK, NULL);
+               _exit(1);
+       }
+       pid = waitpid(pid, &pstat, 0);
+       if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
+               return(-1);
+       return(0);
+}
+
+int
+pw_abort()
+{
+       return(unlink(_PATH_MASTERPASSWD_LOCK));
+}
+
+/* Everything below this point is intended for the convenience of programs
+ * which allow a user to interactively edit the passwd file.  Errors in the
+ * routines below will cause the process to abort. */
+
+static pid_t editpid = -1;
+
+static void
+pw_cont(sig)
+       int sig;
+{
+
+       if (editpid != -1)
+               kill(editpid, sig);
+}
+
+void
+pw_init()
+{
+       struct rlimit rlim;
+
+       /* Unlimited resource limits. */
+       rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+       (void)setrlimit(RLIMIT_CPU, &rlim);
+       (void)setrlimit(RLIMIT_FSIZE, &rlim);
+       (void)setrlimit(RLIMIT_STACK, &rlim);
+       (void)setrlimit(RLIMIT_DATA, &rlim);
+       (void)setrlimit(RLIMIT_RSS, &rlim);
+
+       /* Don't drop core (not really necessary, but GP's). */
+       rlim.rlim_cur = rlim.rlim_max = 0;
+       (void)setrlimit(RLIMIT_CORE, &rlim);
+
+       /* Turn off signals. */
+       (void)signal(SIGALRM, SIG_IGN);
+       (void)signal(SIGHUP, SIG_IGN);
+       (void)signal(SIGINT, SIG_IGN);
+       (void)signal(SIGPIPE, SIG_IGN);
+       (void)signal(SIGQUIT, SIG_IGN);
+       (void)signal(SIGTERM, SIG_IGN);
+       (void)signal(SIGCONT, pw_cont);
+}
+
+void
+pw_edit(notsetuid, filename)
+       int notsetuid;
+       const char *filename;
+{
+       int i, xargc, pstat;
+       char *p, *editor;
+       char **xargv;
+#ifdef __GNUC__
+       (void) &editor;
+#endif
+
+       if (filename == NULL)
+               filename = _PATH_MASTERPASSWD_LOCK;
+       if ((editor = getenv("EDITOR")) == NULL)
+               editor = strdup(_PATH_VI);
+       else
+               editor = strdup(editor);
+       if ((p = strrchr(editor, '/')))
+               ++p;
+       else
+               p = editor;
+
+       /* Scan editor string, count spaces, allocate arg vector. */
+       for (i = 0, xargc = 0; p[i] != '\0'; i++) {
+               if (isspace(p[i])) {
+                       while (isspace(p[i++]))
+                               /* skip white space */ ;
+                       if (p[i] == '\0')
+                               break;
+                       xargc++;
+               }
+       }
+
+       /* argv[0] + <xargc args> + filename + NULL */
+       xargv = (char **)malloc(sizeof(char *) * (xargc + 3));
+       if (xargv == NULL)
+               pw_error("malloc failed", 1, 1);
+
+       i = 0;
+       xargv[i++] = p;
+       for (; *p != '\0'; p++) {
+               if (isspace(*p)) {
+                       while(isspace(*p))
+                               *p++ = '\0';    /* blast whitespace */
+                       if (*p == '\0')
+                               break;
+                       xargv[i++] = p;
+               }
+       }
+
+       xargv[i++] = (char *)filename;
+       xargv[i] = NULL;
+
+       if (!(editpid = vfork())) {
+               if (notsetuid) {
+                       setgid(getgid());
+                       setuid(getuid());
+               }
+               execvp(editor, xargv);
+               _exit(1);
+       }
+       for (;;) {
+               editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
+               if (editpid == -1)
+                       pw_error(editor, 1, 1);
+               else if (WIFSTOPPED(pstat))
+                       raise(WSTOPSIG(pstat));
+               else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
+                       break;
+               else
+                       pw_error(editor, 1, 1);
+       }
+       editpid = -1;
+       free(editor);
+       free(xargv);
+}
+
+void
+pw_prompt()
+{
+       int c;
+
+       (void)printf("re-edit the password file? [y]: ");
+       (void)fflush(stdout);
+       c = getchar();
+       if (c != EOF && c != '\n')
+               while (getchar() != '\n');
+       if (c == 'n')
+               pw_error(NULL, 0, 0);
+}
+
+/* for use in pw_copy(). Compare a pw entry to a pw struct. */
+static int
+pw_equal (buf, pw)
+       char *buf;
+       struct passwd *pw;
+{
+       struct passwd buf_pw;
+       int len = strlen (buf);
+       if (buf[len-1] == '\n')
+               buf[len-1] = '\0';
+       if (!pw_scan(buf, &buf_pw, NULL))
+               return 0;
+       return !strcmp(pw->pw_name, buf_pw.pw_name)
+               && pw->pw_uid == buf_pw.pw_uid
+               && pw->pw_gid == buf_pw.pw_gid
+               && !strcmp(pw->pw_class, buf_pw.pw_class)
+               && (long)pw->pw_change == (long)buf_pw.pw_change
+               && (long)pw->pw_expire == (long)buf_pw.pw_expire
+               && !strcmp(pw->pw_gecos, buf_pw.pw_gecos)
+               && !strcmp(pw->pw_dir, buf_pw.pw_dir)
+               && !strcmp(pw->pw_shell, buf_pw.pw_shell);
+}
+
+void
+pw_copy(ffd, tfd, pw, old_pw)
+       int ffd, tfd;
+       struct passwd *pw, *old_pw;
+{
+       FILE *from, *to;
+       int done;
+       char *p, buf[8192];
+
+       if (!(from = fdopen(ffd, "r")))
+               pw_error(_PATH_MASTERPASSWD, 1, 1);
+       if (!(to = fdopen(tfd, "w")))
+               pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1);
+
+       for (done = 0; fgets(buf, sizeof(buf), from);) {
+               if (!strchr(buf, '\n')) {
+                       warnx("%s: line too long", _PATH_MASTERPASSWD);
+                       pw_error(NULL, 0, 1);
+               }
+               if (done) {
+                       (void)fprintf(to, "%s", buf);
+                       if (ferror(to))
+                               goto err;
+                       continue;
+               }
+               if (buf[0] == '#') {
+                       /* skip comments for Rhapsody. */
+                       continue;
+               }
+               if (!(p = strchr(buf, ':'))) {
+                       warnx("%s: corrupted entry", _PATH_MASTERPASSWD);
+                       pw_error(NULL, 0, 1);
+               }
+               *p = '\0';
+               if (strcmp(buf, pw->pw_name)) {
+                       *p = ':';
+                       (void)fprintf(to, "%s", buf);
+                       if (ferror(to))
+                               goto err;
+                       continue;
+               }
+               *p = ':';
+               if (old_pw && !pw_equal(buf, old_pw)) {
+                       warnx("%s: entry inconsistent",
+                             _PATH_MASTERPASSWD);
+                       pw_error(NULL, 0, 1);
+               }
+               (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
+                   pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
+                   pw->pw_class, (long)pw->pw_change, (long)pw->pw_expire,
+                   pw->pw_gecos, pw->pw_dir, pw->pw_shell);
+               done = 1;
+               if (ferror(to))
+                       goto err;
+       }
+       /* Only append a new entry if real uid is root! */
+       if (!done) 
+               if (getuid() == 0)
+                       (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
+                           pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
+                           pw->pw_class, (long)pw->pw_change,
+                           (long)pw->pw_expire, pw->pw_gecos, pw->pw_dir,
+                           pw->pw_shell);
+               else
+                       warnx("%s: changes not made, no such entry",
+                           _PATH_MASTERPASSWD);
+
+       if (ferror(to))
+err:           pw_error(NULL, 1, 1);
+       (void)fclose(to);
+}
+
+int
+pw_scan(bp, pw, flags)
+       char *bp;
+       struct passwd *pw;
+       int *flags;
+{
+       unsigned long id;
+       int root;
+       char *p, *sh, *ep;
+
+       if (flags != (int *)NULL)
+               *flags = 0;
+
+       if (!(pw->pw_name = strsep(&bp, ":")))          /* login */
+               goto fmt;
+       root = !strcmp(pw->pw_name, "root");
+
+       if (!(pw->pw_passwd = strsep(&bp, ":")))        /* passwd */
+               goto fmt;
+
+       if (!(p = strsep(&bp, ":")))                    /* uid */
+               goto fmt;
+       id = strtoul(p, &ep, 10);
+       if (root && id) {
+               warnx("root uid should be 0");
+               return (0);
+       }
+       if (id > UID_MAX || *ep != '\0') {
+               warnx("invalid uid '%s'", p);
+               return (0);
+       }
+       pw->pw_uid = (uid_t)id;
+       if ((*p == '\0') && (flags != (int *)NULL))
+               *flags |= _PASSWORD_NOUID;
+
+       if (!(p = strsep(&bp, ":")))                    /* gid */
+               goto fmt;
+       id = strtoul(p, &ep, 10);
+       if (id > GID_MAX || *ep != '\0') {
+               warnx("invalid gid '%s'", p);
+               return (0);
+       }
+       pw->pw_gid = (gid_t)id;
+       if ((*p == '\0') && (flags != (int *)NULL))
+               *flags |= _PASSWORD_NOGID;
+
+       pw->pw_class = strsep(&bp, ":");                /* class */
+       if (!(p = strsep(&bp, ":")))                    /* change */
+               goto fmt;
+       pw->pw_change = atol(p);
+       if ((*p == '\0') && (flags != (int *)NULL))
+               *flags |= _PASSWORD_NOCHG;
+       if (!(p = strsep(&bp, ":")))                    /* expire */
+               goto fmt;
+       pw->pw_expire = atol(p);
+       if ((*p == '\0') && (flags != (int *)NULL))
+               *flags |= _PASSWORD_NOEXP;
+       pw->pw_gecos = strsep(&bp, ":");                /* gecos */
+       pw->pw_dir = strsep(&bp, ":");                  /* directory */
+       if (!(pw->pw_shell = strsep(&bp, ":")))         /* shell */
+               goto fmt;
+
+       p = pw->pw_shell;
+       if (root && *p)                                 /* empty == /bin/sh */
+               for (setusershell();;) {
+                       if (!(sh = getusershell())) {
+                               warnx("warning, unknown root shell");
+                               break;
+                       }
+                       if (!strcmp(p, sh))
+                               break;  
+               }
+
+       if ((p = strsep(&bp, ":"))) {                   /* too many */
+fmt:           warnx("corrupted entry");
+               return (0);
+       }
+
+       return (1);
+}
+
+void
+pw_error(name, err, eval)
+       const char *name;
+       int err, eval;
+{
+       if (err)
+               warn(name);
+
+       warnx("%s: unchanged", _PATH_MASTERPASSWD);
+       pw_abort();
+       exit(eval);
+}
+
diff --git a/rpc_yppasswdd.tproj/rpc.yppasswdd.8 b/rpc_yppasswdd.tproj/rpc.yppasswdd.8
new file mode 100644 (file)
index 0000000..8cda3b5
--- /dev/null
@@ -0,0 +1,97 @@
+.\"    $OpenBSD: rpc.yppasswdd.8,v 1.7 1997/08/19 07:00:50 niklas Exp $
+.\"
+.\" Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"
+.Dd July 3, 1994
+.Dt RPC.YPPASSWDD 8
+.Os
+.Sh NAME
+.Nm rpc.yppasswdd
+.Nd YP update password file daemon
+.Sh SYNOPSIS
+.Nm rpc.yppasswdd
+.Op Fl d Ar directory
+.Op Fl noshell
+.Op Fl nogecos
+.Op Fl nopw
+.Op Fl m Ar arg1 arg2 ... 
+.Sh DESCRIPTION
+.Nm rpc.yppasswdd
+must be running on the YP master server to allow users to change information
+in the password file. If the user needs to change his password this is
+normally done with a program called
+.Nm yppasswd .
+This program doesn't exist in OpenBSD but is integrated into
+.Xr passwd 1 .
+.Nm passwd
+will automatically determine which password database should
+be modified.
+To force a change of a YP password when a local one also exists, use
+.Nm passwd -y .
+.Pp
+Other user information can be changed with
+.Xr chpass 1 .
+.Pp
+If the file
+.Nm /var/yp/yppasswdd.log
+exists then messages will be written to the file.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar directory
+Use the specified directory to get at the password-related files instead
+of /etc.
+.It Fl noshell
+Don't allow changes of the shell field in the passwd file.
+.It Fl nogecos
+Don't allow changes of the gecos field in the passwd file.
+.It Fl nopw
+Don't allow changes of the password in the passwd file.
+.It Fl m Ar arg1 arg2 ...
+Don't use 
+.Ar /var/yp/securenet .
+Use another file with another file format. For futher information see
+man page for
+.Ar ypserv.acl .
+.El
+.Sh FILES
+.Bl -tag -width /var/yp/yppasswdd.log -compact
+.It Pa /var/yp/yppasswdd.log
+.It Pa /etc/passwd
+.It Pa /etc/master.passwd
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr ypserv.acl 5 ,
+.Xr securenet 5 ,
+.Xr ypbind 1 
+.Sh AUTHOR
+Mats O Jansson <moj@stacken.kth.se>
diff --git a/rpc_yppasswdd.tproj/rpc.yppasswdd.c b/rpc_yppasswdd.tproj/rpc.yppasswdd.c
new file mode 100644 (file)
index 0000000..1a88517
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: rpc.yppasswdd.c,v 1.9 1997/08/19 07:00:51 niklas Exp $        */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: rpc.yppasswdd.c,v 1.9 1997/08/19 07:00:51 niklas Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pwd.h>
+#include <util.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+#include "yppasswd.h"
+
+static void yppasswddprog_1();
+void    sig_child();
+
+int     noshell, nogecos, nopw, domake;
+char    make_arg[1024] = "make";
+char   *progname = "yppasswdd";
+char   *tempname;
+int    debug = 0;
+
+void
+usage()
+{
+       fprintf(stderr, "%s%s",
+           "usage: rpc.yppasswdd ",
+           "[-d] [-noshell] [-nogecos] [-nopw] [-m arg1 arg2 ... ]\n");
+       exit(1);
+}
+
+int
+main(argc, argv)
+       int     argc;
+       char   *argv[];
+{
+       SVCXPRT *transp;
+       int     i = 1;
+
+       while (i < argc) {
+               if (argv[i][0] == '-') {
+                       if (strcmp("-noshell", argv[i]) == 0) {
+                               noshell = 1;
+                       } else if (strcmp("-nogecos", argv[i]) == 0) {
+                               nogecos = 1;
+                       } else if (strcmp("-nopw", argv[i]) == 0) {
+                               nopw = 1;
+                       } else if (strcmp("-m", argv[i]) == 0) {
+                               domake = 1;
+                               while (i < argc) {
+                                       strcat(make_arg, " ");
+                                       strcat(make_arg, argv[i]);
+                                       i++;
+                               }
+                       } else if (strcmp("-d", argv[i]) == 0) {
+                               debug = 1;
+                       } else
+                               usage();
+                       i++;
+               } else
+                       usage();
+       }
+
+       if (debug == 0) {
+               (void) daemon(0, 0);
+       }
+       chdir("/etc");
+
+/*
+       freopen("/dev/null", "r", stdin);
+       freopen("/var/yp/stderr", "w", stderr);
+       freopen("/var/yp/stdout", "w", stdout);
+*/
+       (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS);
+
+       (void) signal(SIGCHLD, sig_child);
+
+       transp = svcudp_create(RPC_ANYSOCK);
+       if (transp == NULL) {
+               (void) fprintf(stderr, "cannot create udp service.\n");
+               exit(1);
+       }
+       if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswddprog_1,
+           IPPROTO_UDP)) {
+               fprintf(stderr, "unable to register YPPASSWDPROG, YPPASSWDVERS, udp\n");
+               exit(1);
+       }
+       transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+       if (transp == NULL) {
+               (void) fprintf(stderr, "cannot create tcp service.\n");
+               exit(1);
+       }
+       if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswddprog_1,
+           IPPROTO_TCP)) {
+               fprintf(stderr, "unable to register YPPASSWDPROG, YPPASSWDVERS, tcp\n");
+               exit(1);
+       }
+       svc_run();
+       (void) fprintf(stderr, "svc_run returned\n");
+       exit(1);
+}
+
+static void
+yppasswddprog_1(rqstp, transp)
+       struct svc_req *rqstp;
+       SVCXPRT *transp;
+{
+       union {
+               yppasswd yppasswdproc_update_1_arg;
+       }       argument;
+       char   *result;
+       bool_t(*xdr_argument) (), (*xdr_result) ();
+       char   *(*local) ();
+
+       switch (rqstp->rq_proc) {
+       case NULLPROC:
+               (void) svc_sendreply(transp, xdr_void, (char *) NULL);
+               return;
+       case YPPASSWDPROC_UPDATE:
+               xdr_argument = xdr_yppasswd;
+               xdr_result = xdr_int;
+               local = (char *(*) ()) yppasswdproc_update_1_svc;
+               break;
+       default:
+               svcerr_noproc(transp);
+               return;
+       }
+       bzero((char *) &argument, sizeof(argument));
+       if (!svc_getargs(transp, xdr_argument, (caddr_t) & argument)) {
+               svcerr_decode(transp);
+               return;
+       }
+       result = (*local) (&argument, rqstp, transp);
+}
+
+void
+sig_child()
+{
+       int save_errno = errno;
+
+       while (wait3((int *) NULL, WNOHANG, (struct rusage *) NULL) > 0)
+               ;
+       errno = save_errno;
+}
diff --git a/rpc_yppasswdd.tproj/yppasswd.h b/rpc_yppasswdd.tproj/yppasswd.h
new file mode 100644 (file)
index 0000000..5592e87
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppasswd.h,v 1.4 1997/08/19 07:00:51 niklas Exp $*/
+
+/*
+ * Copyright (c) 1995 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _YPPASSWD_H_RPCGEN
+#define _YPPASSWD_H_RPCGEN
+
+struct x_passwd {
+       char *pw_name;
+       char *pw_passwd;
+       int pw_uid;
+       int pw_gid;
+       char *pw_gecos;
+       char *pw_dir;
+       char *pw_shell;
+};
+typedef struct x_passwd x_passwd;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_x_passwd(XDR *, x_passwd*);
+#elif defined(__STDC__)
+extern  bool_t xdr_x_passwd(XDR *, x_passwd*);
+#else /* Old Style C */
+bool_t xdr_x_passwd();
+#endif /* Old Style C */
+
+
+struct yppasswd {
+       char *oldpass;
+       x_passwd newpw;
+};
+typedef struct yppasswd yppasswd;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_yppasswd(XDR *, yppasswd*);
+#elif defined(__STDC__)
+extern  bool_t xdr_yppasswd(XDR *, yppasswd*);
+#else /* Old Style C */ 
+bool_t xdr_yppasswd();
+#endif /* Old Style C */ 
+
+
+#define YPPASSWDPROG ((u_long)100009)
+#define YPPASSWDVERS ((u_long)1)
+
+#ifdef __cplusplus
+#define YPPASSWDPROC_UPDATE ((u_long)1)
+extern "C" int * yppasswdproc_update_1(yppasswd *, CLIENT *);
+extern "C" int * yppasswdproc_update_1_svc(yppasswd *, struct svc_req *, SVCXPRT *);
+
+#elif defined(__STDC__)
+#define YPPASSWDPROC_UPDATE ((u_long)1)
+extern  int * yppasswdproc_update_1(yppasswd *, CLIENT *);
+extern  int * yppasswdproc_update_1_svc(yppasswd *, struct svc_req *, SVCXPRT *);
+
+#else /* Old Style C */ 
+#define YPPASSWDPROC_UPDATE ((u_long)1)
+extern  int * yppasswdproc_update_1();
+extern  int * yppasswdproc_update_1_svc();
+#endif /* Old Style C */ 
+
+#endif /* !_YPPASSWD_H_RPCGEN */
diff --git a/rpc_yppasswdd.tproj/yppasswdd_mkpw.c b/rpc_yppasswdd.tproj/yppasswdd_mkpw.c
new file mode 100644 (file)
index 0000000..6904c44
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppasswdd_mkpw.c,v 1.16 1997/11/17 23:56:20 gene Exp $        */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: yppasswdd_mkpw.c,v 1.16 1997/11/17 23:56:20 gene Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yppasswd.h>
+#include <db.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <util.h>
+#include <ctype.h>
+#include <string.h>
+#include <syslog.h>
+#include <err.h>
+
+extern int noshell;
+extern int nogecos;
+extern int nopw;
+extern int make;
+extern char make_arg[];
+
+static void _pw_copy(int, int, struct passwd *);
+
+/* This is imported from OpenBSD's libutil because it's argument
+ * incompatible with NetBSD's. However, the NetBSD libutil is
+ * at least what the prototypes suggest is in System.framework,
+ * even though I can't find the code. I assume it will be there
+ * eventually. We need to use NetBSD's because it works with the
+ * pwd_mkdb binary that's shipped with Rhapsody. This is an area
+ * where OpenBSD diverges; however, we wanted to keep the OpenBSD
+ * rpc.yppasswdd because the rest of our YP code is from OpenBSD.
+ * What a mess.
+ */
+static void
+_pw_copy(ffd, tfd, pw)
+       int ffd, tfd;
+       struct passwd *pw;
+{
+       FILE   *from, *to;
+       int     done;
+       char   *p, buf[8192];
+
+       if (!(from = fdopen(ffd, "r")))
+               pw_error(_PATH_MASTERPASSWD, 1, 1);
+       if (!(to = fdopen(tfd, "w")))
+               pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1);
+
+       for (done = 0; fgets(buf, sizeof(buf), from);) {
+               if (!strchr(buf, '\n')) {
+                       warnx("%s: line too long", _PATH_MASTERPASSWD);
+                       pw_error(NULL, 0, 1);
+               }
+               if (done) {
+                       (void)fprintf(to, "%s", buf);
+                       if (ferror(to))
+                               goto err;
+                       continue;
+               }
+               if (!(p = strchr(buf, ':'))) {
+                       warnx("%s: corrupted entry", _PATH_MASTERPASSWD);
+                       pw_error(NULL, 0, 1);
+               }
+               *p = '\0';
+               if (strcmp(buf, pw->pw_name)) {
+                       *p = ':';
+                       (void)fprintf(to, "%s", buf);
+                       if (ferror(to))
+                               goto err;
+                       continue;
+               }
+               (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
+                   pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
+                   pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos,
+                   pw->pw_dir, pw->pw_shell);
+               done = 1;
+               if (ferror(to))
+                       goto err;
+       }
+       if (!done)
+               (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
+                   pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
+                   pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos,
+                   pw->pw_dir, pw->pw_shell);
+
+       if (ferror(to))
+err:
+       pw_error(NULL, 0, 1);
+       (void)fclose(to);
+}
+
+
+int
+badchars(base)
+       char *base;
+{
+       int ampr = 0;
+       char *s;
+
+       for (s = base; *s; s++) {
+               if (*s == '&')
+                       ampr++;
+               if (!isprint(*s))
+                       return 1;
+               if (strchr(":\n\t\r", *s))
+                       return 1;
+       }
+       if (ampr > 10)
+               return 1;
+       return 0;
+}
+
+int
+subst(s, from, to)
+       char *s;
+       char from, to;
+{
+       int     n = 0;
+
+       while (*s) {
+               if (*s == from) {
+                       *s = to;
+                       n++;
+               }
+               s++;
+       }
+       return (n);
+}
+
+int
+make_passwd(argp)
+       yppasswd *argp;
+{
+       struct passwd pw;
+       int     pfd, tfd;
+       char    buf[10], *bp = NULL, *p, *t;
+       int     n;
+       ssize_t cnt;
+       size_t  resid;
+       struct stat st;
+
+       pw_init();
+       pfd = open(_PATH_MASTERPASSWD, O_RDONLY);
+       if (pfd < 0)
+               goto fail;
+       if (fstat(pfd, &st))
+               goto fail;
+       p = bp = malloc((resid = st.st_size) + 1);
+       do {
+               cnt = read(pfd, p, resid);
+               if (cnt < 0)
+                       goto fail;
+               p += cnt;
+               resid -= cnt;
+       } while (resid > 0);
+       close(pfd);
+       pfd = -1;
+       *p = '\0';              /* Buf oflow prevention */
+
+       p = bp;
+       subst(p, '\n', '\0');
+       for (n = 1; p < bp + st.st_size; n++, p = t) {
+               t = strchr(p, '\0') + 1;
+               /* Rhapsody allows the passwd file to have comments in it. */
+               if (p[0] == '#') {
+                       continue;
+               }
+               cnt = subst(p, ':', '\0');
+               if (cnt != 9) {
+                       syslog(LOG_WARNING, "bad entry at line %d of %s", n,
+                           _PATH_MASTERPASSWD);
+                       continue;
+               }
+
+               if (strcmp(p, argp->newpw.pw_name) == 0)
+                       break;
+       }
+       if (p >= bp + st.st_size)
+               goto fail;
+
+#define        EXPAND(e)       e = p; while (*p++);
+       EXPAND(pw.pw_name);
+       EXPAND(pw.pw_passwd);
+       pw.pw_uid = atoi(p); EXPAND(t);
+       pw.pw_gid = atoi(p); EXPAND(t);
+       EXPAND(pw.pw_class);
+       pw.pw_change = (time_t)atol(p); EXPAND(t);
+       pw.pw_expire = (time_t)atol(p); EXPAND(t);
+       EXPAND(pw.pw_gecos);
+       EXPAND(pw.pw_dir);
+       EXPAND(pw.pw_shell);
+
+       /* crypt() is broken under Rhapsody. It doesn't deal with
+        * empty keys or salts like other Unices.
+        */
+       if (pw.pw_passwd[0] != '\0' && argp->oldpass != NULL && argp->oldpass[0] != '\0') {
+               if (strcmp(crypt(argp->oldpass, pw.pw_passwd), pw.pw_passwd) != 0)
+                       goto fail;
+       }
+       
+       if (!nopw && badchars(argp->newpw.pw_passwd))
+               goto fail;
+       if (!nogecos && badchars(argp->newpw.pw_gecos))
+               goto fail;
+       if (!nogecos && badchars(argp->newpw.pw_shell))
+               goto fail;
+
+       /*
+        * Get the new password.  Reset passwd change time to zero; when
+        * classes are implemented, go and get the "offset" value for this
+        * class and reset the timer.
+        */
+       if (!nopw) {
+               pw.pw_passwd = argp->newpw.pw_passwd;
+               pw.pw_change = 0;
+       }
+       if (!nogecos)
+               pw.pw_gecos = argp->newpw.pw_gecos;
+       if (!noshell)
+               pw.pw_shell = argp->newpw.pw_shell;
+
+       for (n = 0, p = pw.pw_gecos; *p; p++)
+               if (*p == '&')
+                       n = n + strlen(pw.pw_name) - 1;
+       if (strlen(pw.pw_name) + 1 + strlen(pw.pw_passwd) + 1 +
+           strlen((sprintf(buf, "%d", pw.pw_uid), buf)) + 1 +
+           strlen((sprintf(buf, "%d", pw.pw_gid), buf)) + 1 +
+           strlen(pw.pw_gecos) + n + 1 + strlen(pw.pw_dir) + 1 +
+           strlen(pw.pw_shell) >= 1023)
+               goto fail;
+
+       pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
+       if (pfd < 0) {
+               syslog(LOG_ERR, "cannot open %s", _PATH_MASTERPASSWD);
+               goto fail;
+       }
+
+       tfd = pw_lock(0);
+       if (tfd < 0)
+               goto fail;
+
+       _pw_copy(pfd, tfd, &pw);
+       pw_mkdb();
+       free(bp);
+
+       if (fork() == 0) {
+               chdir("/var/yp");
+               (void)umask(022);
+               system(make_arg);
+               exit(0);
+       }
+       return (0);
+
+fail:
+       if (bp)
+               free(bp);
+       if (pfd >= 0)
+               close(pfd);
+       return (1);
+}
diff --git a/rpc_yppasswdd.tproj/yppasswdd_proc.c b/rpc_yppasswdd.tproj/yppasswdd_proc.c
new file mode 100644 (file)
index 0000000..2053263
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppasswdd_proc.c,v 1.5 1997/08/19 07:00:52 niklas Exp $       */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: yppasswdd_proc.c,v 1.5 1997/08/19 07:00:52 niklas Exp $";
+#endif
+
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "yppasswd.h"
+
+int make_passwd __P((yppasswd *));
+
+int *
+yppasswdproc_update_1_svc(argp, rqstp, transp)
+       yppasswd *argp;
+       struct svc_req *rqstp;
+       SVCXPRT *transp;
+{
+       static int res;
+
+       bzero((char *)&res, sizeof(res));
+       res = make_passwd(argp);
+
+       if (!svc_sendreply(transp, xdr_int, (char *)&res))
+               svcerr_systemerr(transp);
+
+       if (!svc_freeargs(transp, xdr_yppasswd, (caddr_t) argp)) {
+               (void)fprintf(stderr, "unable to free arguments\n");
+               exit(1);
+       }
+       return ((void *)&res);
+}
diff --git a/rpcinfo.tproj/Makefile b/rpcinfo.tproj/Makefile
new file mode 100644 (file)
index 0000000..808dfe4
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rpcinfo
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = rpcinfo.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
+            h.template
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rpcinfo.tproj/Makefile.postamble b/rpcinfo.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7ede358
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
diff --git a/rpcinfo.tproj/Makefile.preamble b/rpcinfo.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..30aa1b5
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+INSTALLDIR = /usr/sbin
diff --git a/rpcinfo.tproj/PB.project b/rpcinfo.tproj/PB.project
new file mode 100644 (file)
index 0000000..00a575f
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        LIBRARYSEARCH = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (rpcinfo.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_MAINNIB = rpcinfo; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_MAINNIB = rpcinfo; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rpcinfo; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_MAINNIB = rpcinfo; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rpcinfo.tproj/h.template b/rpcinfo.tproj/h.template
new file mode 100644 (file)
index 0000000..5dcbc5d
--- /dev/null
@@ -0,0 +1,9 @@
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+@interface $FILENAMESANSEXTENSION$ : Object
+{
+
+}
+
+@end
diff --git a/rpcinfo.tproj/m.template b/rpcinfo.tproj/m.template
new file mode 100644 (file)
index 0000000..1216fe5
--- /dev/null
@@ -0,0 +1,18 @@
+$$ Lines starting with $$ are not inserted into newly created files
+$$ The following substitutions are made:
+$$
+$$ $FILENAME$                e.g. foo.m
+$$ $FILENAMESANSEXTENSION$   e.g. foo
+$$ $DIRECTORY$               e.g. /tmp/MyNewApp
+$$ $PROJECTNAME$             e.g. MyNewApp
+$$ $SUBPROJECTNAME$          e.g. TheGoodPart.subproj
+$$ $USERNAME$                e.g. mwagner
+$$ $DATE$                    e.g. Jan-1-1994
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import "$FILENAMESANSEXTENSION$.h"
+
+@implementation $FILENAMESANSEXTENSION$
+
+@end
diff --git a/rpcinfo.tproj/rpcinfo.c b/rpcinfo.tproj/rpcinfo.c
new file mode 100644 (file)
index 0000000..3315bda
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* @(#)rpcinfo.c       2.2 88/08/11 4.0 RPCSRC */
+#ifndef lint
+static char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
+#endif
+
+/*
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * rpcinfo: ping a particular rpc program
+ *     or dump the portmapper
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <signal.h>
+#include <ctype.h>
+
+#define MAXHOSTLEN 256
+
+#define        MIN_VERS        ((u_long) 0)
+#define        MAX_VERS        ((u_long) 4294967295L)
+
+static void    udpping(/*u_short portflag, int argc, char **argv*/);
+static void    tcpping(/*u_short portflag, int argc, char **argv*/);
+static int     pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
+static void    pmapdump(/*int argc, char **argv*/);
+static bool_t  reply_proc(/*void *res, struct sockaddr_in *who*/);
+static void    brdcst(/*int argc, char **argv*/);
+static void    deletereg(/* int argc, char **argv */) ;
+static void    usage(/*void*/);
+static u_long  getprognum(/*char *arg*/);
+static u_long  getvers(/*char *arg*/);
+static void    get_inet_address(/*struct sockaddr_in *addr, char *host*/);
+extern u_long inet_addr();  /* in 4.2BSD, arpa/inet.h called that a in_addr */
+extern char *inet_ntoa();
+
+/*
+ * Functions to be performed.
+ */
+#define        NONE            0       /* no function */
+#define        PMAPDUMP        1       /* dump portmapper registrations */
+#define        TCPPING         2       /* ping TCP service */
+#define        UDPPING         3       /* ping UDP service */
+#define        BRDCST          4       /* ping broadcast UDP service */
+#define DELETES                5       /* delete registration for the service */
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       register int c;
+       extern char *optarg;
+       extern int optind;
+       int errflg;
+       int function;
+       u_short portnum;
+
+       function = NONE;
+       portnum = 0;
+       errflg = 0;
+       while ((c = getopt(argc, argv, "ptubdn:")) != EOF) {
+               switch (c) {
+
+               case 'p':
+                       if (function != NONE)
+                               errflg = 1;
+                       else
+                               function = PMAPDUMP;
+                       break;
+
+               case 't':
+                       if (function != NONE)
+                               errflg = 1;
+                       else
+                               function = TCPPING;
+                       break;
+
+               case 'u':
+                       if (function != NONE)
+                               errflg = 1;
+                       else
+                               function = UDPPING;
+                       break;
+
+               case 'b':
+                       if (function != NONE)
+                               errflg = 1;
+                       else
+                               function = BRDCST;
+                       break;
+
+               case 'n':
+                       portnum = (u_short) atoi(optarg);   /* hope we don't get bogus # */
+                       break;
+
+               case 'd':
+                       if (function != NONE)
+                               errflg = 1;
+                       else
+                               function = DELETES;
+                       break;
+
+               case '?':
+                       errflg = 1;
+               }
+       }
+
+       if (errflg || function == NONE) {
+               usage();
+               return (1);
+       }
+
+       switch (function) {
+
+       case PMAPDUMP:
+               if (portnum != 0) {
+                       usage();
+                       return (1);
+               }
+               pmapdump(argc - optind, argv + optind);
+               break;
+
+       case UDPPING:
+               udpping(portnum, argc - optind, argv + optind);
+               break;
+
+       case TCPPING:
+               tcpping(portnum, argc - optind, argv + optind);
+               break;
+
+       case BRDCST:
+               if (portnum != 0) {
+                       usage();
+                       return (1);
+               }
+               brdcst(argc - optind, argv + optind);
+               break;
+
+       case DELETES:
+               deletereg(argc - optind, argv + optind);
+               break;
+       }
+
+       return (0);
+}
+               
+static void
+udpping(portnum, argc, argv)
+       u_short portnum;
+       int argc;
+       char **argv;
+{
+       struct timeval to;
+       struct sockaddr_in addr;
+       enum clnt_stat rpc_stat;
+       CLIENT *client;
+       u_long prognum, vers, minvers, maxvers;
+       int sock = RPC_ANYSOCK;
+       struct rpc_err rpcerr;
+       int failure;
+    
+       if (argc < 2 || argc > 3) {
+               usage();
+               exit(1);
+       }
+       prognum = getprognum(argv[1]);
+       get_inet_address(&addr, argv[0]);
+       /* Open the socket here so it will survive calls to clnt_destroy */
+       sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (sock < 0) {
+               perror("rpcinfo: socket");
+               exit(1);
+       }
+       failure = 0;
+       if (argc == 2) {
+               /*
+                * A call to version 0 should fail with a program/version
+                * mismatch, and give us the range of versions supported.
+                */
+               addr.sin_port = htons(portnum);
+               to.tv_sec = 5;
+               to.tv_usec = 0;
+               if ((client = clntudp_create(&addr, prognum, (u_long)0,
+                   to, &sock)) == NULL) {
+                       clnt_pcreateerror("rpcinfo");
+                       printf("program %lu is not available\n",
+                           prognum);
+                       exit(1);
+               }
+               to.tv_sec = 10;
+               to.tv_usec = 0;
+               rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
+                   xdr_void, (char *)NULL, to);
+               if (rpc_stat == RPC_PROGVERSMISMATCH) {
+                       clnt_geterr(client, &rpcerr);
+                       minvers = rpcerr.re_vers.low;
+                       maxvers = rpcerr.re_vers.high;
+               } else if (rpc_stat == RPC_SUCCESS) {
+                       /*
+                        * Oh dear, it DOES support version 0.
+                        * Let's try version MAX_VERS.
+                        */
+                       addr.sin_port = htons(portnum);
+                       to.tv_sec = 5;
+                       to.tv_usec = 0;
+                       if ((client = clntudp_create(&addr, prognum, MAX_VERS,
+                           to, &sock)) == NULL) {
+                               clnt_pcreateerror("rpcinfo");
+                               printf("program %lu version %lu is not available\n",
+                                   prognum, MAX_VERS);
+                               exit(1);
+                       }
+                       to.tv_sec = 10;
+                       to.tv_usec = 0;
+                       rpc_stat = clnt_call(client, NULLPROC, xdr_void,
+                           (char *)NULL, xdr_void, (char *)NULL, to);
+                       if (rpc_stat == RPC_PROGVERSMISMATCH) {
+                               clnt_geterr(client, &rpcerr);
+                               minvers = rpcerr.re_vers.low;
+                               maxvers = rpcerr.re_vers.high;
+                       } else if (rpc_stat == RPC_SUCCESS) {
+                               /*
+                                * It also supports version MAX_VERS.
+                                * Looks like we have a wise guy.
+                                * OK, we give them information on all
+                                * 4 billion versions they support...
+                                */
+                               minvers = 0;
+                               maxvers = MAX_VERS;
+                       } else {
+                               (void) pstatus(client, prognum, MAX_VERS);
+                               exit(1);
+                       }
+               } else {
+                       (void) pstatus(client, prognum, (u_long)0);
+                       exit(1);
+               }
+               clnt_destroy(client);
+               for (vers = minvers; vers <= maxvers; vers++) {
+                       addr.sin_port = htons(portnum);
+                       to.tv_sec = 5;
+                       to.tv_usec = 0;
+                       if ((client = clntudp_create(&addr, prognum, vers,
+                           to, &sock)) == NULL) {
+                               clnt_pcreateerror("rpcinfo");
+                               printf("program %lu version %lu is not available\n",
+                                   prognum, vers);
+                               exit(1);
+                       }
+                       to.tv_sec = 10;
+                       to.tv_usec = 0;
+                       rpc_stat = clnt_call(client, NULLPROC, xdr_void,
+                           (char *)NULL, xdr_void, (char *)NULL, to);
+                       if (pstatus(client, prognum, vers) < 0)
+                               failure = 1;
+                       clnt_destroy(client);
+               }
+       }
+       else {
+               vers = getvers(argv[2]);
+               addr.sin_port = htons(portnum);
+               to.tv_sec = 5;
+               to.tv_usec = 0;
+               if ((client = clntudp_create(&addr, prognum, vers,
+                   to, &sock)) == NULL) {
+                       clnt_pcreateerror("rpcinfo");
+                       printf("program %lu version %lu is not available\n",
+                           prognum, vers);
+                       exit(1);
+               }
+               to.tv_sec = 10;
+               to.tv_usec = 0;
+               rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
+                   xdr_void, (char *)NULL, to);
+               if (pstatus(client, prognum, vers) < 0)
+                       failure = 1;
+       }
+       (void) close(sock); /* Close it up again */
+       if (failure)
+               exit(1);
+}
+
+static void
+tcpping(portnum, argc, argv)
+       u_short portnum;
+       int argc;
+       char **argv;
+{
+       struct timeval to;
+       struct sockaddr_in addr;
+       enum clnt_stat rpc_stat;
+       CLIENT *client;
+       u_long prognum, vers, minvers, maxvers;
+       int sock = RPC_ANYSOCK;
+       struct rpc_err rpcerr;
+       int failure;
+
+       if (argc < 2 || argc > 3) {
+               usage();
+               exit(1);
+       }
+       prognum = getprognum(argv[1]);
+       get_inet_address(&addr, argv[0]);
+       failure = 0;
+       if (argc == 2) {
+               /*
+                * A call to version 0 should fail with a program/version
+                * mismatch, and give us the range of versions supported.
+                */
+               addr.sin_port = htons(portnum);
+               if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
+                   &sock, 0, 0)) == NULL) {
+                       clnt_pcreateerror("rpcinfo");
+                       printf("program %lu is not available\n",
+                           prognum);
+                       exit(1);
+               }
+               to.tv_sec = 10;
+               to.tv_usec = 0;
+               rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
+                   xdr_void, (char *)NULL, to);
+               if (rpc_stat == RPC_PROGVERSMISMATCH) {
+                       clnt_geterr(client, &rpcerr);
+                       minvers = rpcerr.re_vers.low;
+                       maxvers = rpcerr.re_vers.high;
+               } else if (rpc_stat == RPC_SUCCESS) {
+                       /*
+                        * Oh dear, it DOES support version 0.
+                        * Let's try version MAX_VERS.
+                        */
+                       addr.sin_port = htons(portnum);
+                       if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
+                           &sock, 0, 0)) == NULL) {
+                               clnt_pcreateerror("rpcinfo");
+                               printf("program %lu version %lu is not available\n",
+                                   prognum, MAX_VERS);
+                               exit(1);
+                       }
+                       to.tv_sec = 10;
+                       to.tv_usec = 0;
+                       rpc_stat = clnt_call(client, NULLPROC, xdr_void,
+                           (char *)NULL, xdr_void, (char *)NULL, to);
+                       if (rpc_stat == RPC_PROGVERSMISMATCH) {
+                               clnt_geterr(client, &rpcerr);
+                               minvers = rpcerr.re_vers.low;
+                               maxvers = rpcerr.re_vers.high;
+                       } else if (rpc_stat == RPC_SUCCESS) {
+                               /*
+                                * It also supports version MAX_VERS.
+                                * Looks like we have a wise guy.
+                                * OK, we give them information on all
+                                * 4 billion versions they support...
+                                */
+                               minvers = 0;
+                               maxvers = MAX_VERS;
+                       } else {
+                               (void) pstatus(client, prognum, MAX_VERS);
+                               exit(1);
+                       }
+               } else {
+                       (void) pstatus(client, prognum, MIN_VERS);
+                       exit(1);
+               }
+               clnt_destroy(client);
+               (void) close(sock);
+               sock = RPC_ANYSOCK; /* Re-initialize it for later */
+               for (vers = minvers; vers <= maxvers; vers++) {
+                       addr.sin_port = htons(portnum);
+                       if ((client = clnttcp_create(&addr, prognum, vers,
+                           &sock, 0, 0)) == NULL) {
+                               clnt_pcreateerror("rpcinfo");
+                               printf("program %lu version %lu is not available\n",
+                                   prognum, vers);
+                               exit(1);
+                       }
+                       to.tv_usec = 0;
+                       to.tv_sec = 10;
+                       rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
+                           xdr_void, (char *)NULL, to);
+                       if (pstatus(client, prognum, vers) < 0)
+                               failure = 1;
+                       clnt_destroy(client);
+                       (void) close(sock);
+                       sock = RPC_ANYSOCK;
+               }
+       }
+       else {
+               vers = getvers(argv[2]);
+               addr.sin_port = htons(portnum);
+               if ((client = clnttcp_create(&addr, prognum, vers, &sock,
+                   0, 0)) == NULL) {
+                       clnt_pcreateerror("rpcinfo");
+                       printf("program %lu version %lu is not available\n",
+                           prognum, vers);
+                       exit(1);
+               }
+               to.tv_usec = 0;
+               to.tv_sec = 10;
+               rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
+                   xdr_void, (char *)NULL, to);
+               if (pstatus(client, prognum, vers) < 0)
+                       failure = 1;
+       }
+       if (failure)
+               exit(1);
+}
+
+/*
+ * This routine should take a pointer to an "rpc_err" structure, rather than
+ * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
+ * a CLIENT structure rather than a pointer to an "rpc_err" structure.
+ * As such, we have to keep the CLIENT structure around in order to print
+ * a good error message.
+ */
+static int
+pstatus(client, prognum, vers)
+       register CLIENT *client;
+       u_long prognum;
+       u_long vers;
+{
+       struct rpc_err rpcerr;
+
+       clnt_geterr(client, &rpcerr);
+       if (rpcerr.re_status != RPC_SUCCESS) {
+               clnt_perror(client, "rpcinfo");
+               printf("program %lu version %lu is not available\n",
+                   prognum, vers);
+               return (-1);
+       } else {
+               printf("program %lu version %lu ready and waiting\n",
+                   prognum, vers);
+               return (0);
+       }
+}
+
+static void
+pmapdump(argc, argv)
+       int argc;
+       char **argv;
+{
+       struct sockaddr_in server_addr;
+       register struct hostent *hp;
+       struct pmaplist *head = NULL;
+       int socket = RPC_ANYSOCK;
+       struct timeval minutetimeout;
+       register CLIENT *client;
+       struct rpcent *rpc;
+       
+       if (argc > 1) {
+               usage();
+               exit(1);
+       }
+       if (argc == 1)
+               get_inet_address(&server_addr, argv[0]);
+       else {
+               bzero((char *)&server_addr, sizeof server_addr);
+               server_addr.sin_family = AF_INET;
+               if ((hp = gethostbyname("localhost")) != NULL)
+                       bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
+                           hp->h_length);
+               else
+                       server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
+       }
+       minutetimeout.tv_sec = 60;
+       minutetimeout.tv_usec = 0;
+       server_addr.sin_port = htons(PMAPPORT);
+       if ((client = clnttcp_create(&server_addr, PMAPPROG,
+           PMAPVERS, &socket, 50, 500)) == NULL) {
+               clnt_pcreateerror("rpcinfo: can't contact portmapper");
+               exit(1);
+       }
+       if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
+           xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
+               fprintf(stderr, "rpcinfo: can't contact portmapper: ");
+               clnt_perror(client, "rpcinfo");
+               exit(1);
+       }
+       if (head == NULL) {
+               printf("No remote programs registered.\n");
+       } else {
+               printf("   program vers proto   port\n");
+               for (; head != NULL; head = head->pml_next) {
+                       printf("%10ld%5ld",
+                           head->pml_map.pm_prog,
+                           head->pml_map.pm_vers);
+                       if (head->pml_map.pm_prot == IPPROTO_UDP)
+                               printf("%6s",  "udp");
+                       else if (head->pml_map.pm_prot == IPPROTO_TCP)
+                               printf("%6s", "tcp");
+                       else
+                               printf("%6ld",  head->pml_map.pm_prot);
+                       printf("%7ld",  head->pml_map.pm_port);
+                       rpc = getrpcbynumber(head->pml_map.pm_prog);
+                       if (rpc)
+                               printf("  %s\n", rpc->r_name);
+                       else
+                               printf("\n");
+               }
+       }
+}
+
+/* 
+ * reply_proc collects replies from the broadcast. 
+ * to get a unique list of responses the output of rpcinfo should
+ * be piped through sort(1) and then uniq(1).
+ */
+
+/*ARGSUSED*/
+static bool_t
+reply_proc(res, who)
+       void *res;              /* Nothing comes back */
+       struct sockaddr_in *who; /* Who sent us the reply */
+{
+       register struct hostent *hp;
+
+       hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
+           AF_INET);
+       printf("%s %s\n", inet_ntoa(who->sin_addr),
+           (hp == NULL) ? "(unknown)" : hp->h_name);
+       return(FALSE);
+}
+
+static void
+brdcst(argc, argv)
+       int argc;
+       char **argv;
+{
+       enum clnt_stat rpc_stat;
+       u_long prognum, vers;
+
+       if (argc != 2) {
+               usage();
+               exit(1);
+       }
+       prognum = getprognum(argv[0]);
+       vers = getvers(argv[1]);
+       rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
+           (char *)NULL, xdr_void, (char *)NULL, reply_proc);
+       if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
+               fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
+                   clnt_sperrno(rpc_stat));
+               exit(1);
+       }
+       exit(0);
+}
+
+static void
+deletereg(argc, argv)
+       int argc;
+       char **argv;
+{      u_long prog_num, version_num ;
+
+       if (argc != 2) {
+               usage() ;
+               exit(1) ;
+       }
+       if (getuid()) { /* This command allowed only to root */
+               fprintf(stderr, "Sorry. You are not root\n") ;
+               exit(1) ;
+       }
+       prog_num = getprognum(argv[0]);
+       version_num = getvers(argv[1]);
+       if ((pmap_unset(prog_num, version_num)) == 0) {
+               fprintf(stderr, "rpcinfo: Could not delete registration for prog %s version %s\n",
+                       argv[0], argv[1]) ;
+               exit(1) ;
+       }
+}
+
+static void
+usage()
+{
+       fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n");
+       fprintf(stderr, "       rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n");
+       fprintf(stderr, "       rpcinfo -p [ host ]\n");
+       fprintf(stderr, "       rpcinfo -b prognum versnum\n");
+       fprintf(stderr, "       rpcinfo -d prognum versnum\n") ;
+}
+
+static u_long
+getprognum(arg)
+       char *arg;
+{
+       register struct rpcent *rpc;
+       register u_long prognum;
+
+       if (isalpha(*arg)) {
+               rpc = getrpcbyname(arg);
+               if (rpc == NULL) {
+                       fprintf(stderr, "rpcinfo: %s is unknown service\n",
+                           arg);
+                       exit(1);
+               }
+               prognum = rpc->r_number;
+       } else {
+               prognum = (u_long) atoi(arg);
+       }
+
+       return (prognum);
+}
+
+static u_long
+getvers(arg)
+       char *arg;
+{
+       register u_long vers;
+
+       vers = (int) atoi(arg);
+       return (vers);
+}
+
+static void
+get_inet_address(addr, host)
+       struct sockaddr_in *addr;
+       char *host;
+{
+       register struct hostent *hp;
+
+       bzero((char *)addr, sizeof *addr);
+       addr->sin_addr.s_addr = (u_long) inet_addr(host);
+       if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
+               if ((hp = gethostbyname(host)) == NULL) {
+                       fprintf(stderr, "rpcinfo: %s is unknown host\n", host);
+                       exit(1);
+               }
+               bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length);
+       }
+       addr->sin_family = AF_INET;
+}
diff --git a/rsh.tproj/Makefile b/rsh.tproj/Makefile
new file mode 100644 (file)
index 0000000..c387527
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rsh
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = rsh.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rsh.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rsh.tproj/Makefile.postamble b/rsh.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..625a231
--- /dev/null
@@ -0,0 +1,5 @@
+VPATH += :../rlogin.tproj
+INSTALL_PERMISSIONS = 4555
+
+after_install::
+       $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
diff --git a/rsh.tproj/Makefile.preamble b/rsh.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..87a4321
--- /dev/null
@@ -0,0 +1,4 @@
+RLOGIN_CFILES = krcmd.c des_rw.c
+OTHER_OFILES = $(RLOGIN_CFILES:.c=.o)
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/rsh.tproj/PB.project b/rsh.tproj/PB.project
new file mode 100644 (file)
index 0000000..33594fc
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        CLASSES = (); 
+        FRAMEWORKS = (); 
+        H_FILES = (pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (rsh.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rsh.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = rsh; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = rsh; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rsh; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = rsh; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rsh.tproj/pathnames.h b/rsh.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..812b0d0
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)pathnames.h   8.1 (Berkeley) 6/6/93
+ */
+
+#define        _PATH_RLOGIN    "/usr/bin/rlogin"
diff --git a/rsh.tproj/rsh.1 b/rsh.tproj/rsh.1
new file mode 100644 (file)
index 0000000..78ec2f1
--- /dev/null
@@ -0,0 +1,187 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)rsh.1       8.2 (Berkeley) 4/29/95
+.\"
+.Dd April 29, 1995
+.Dt RSH 1
+.Os BSD 4.2
+.Sh NAME
+.Nm rsh
+.Nd remote shell
+.Sh SYNOPSIS
+.Nm rsh
+.Op Fl Kdnx
+.Op Fl k Ar realm
+.Op Fl l Ar username
+.Ar host
+.Nm rsh
+.Op Fl Kdnx
+.Op Fl k Ar realm
+.Ar username@host
+.Op command
+.Sh DESCRIPTION
+.Nm Rsh
+executes
+.Ar command
+on
+.Ar host  .
+.Pp
+.Nm Rsh
+copies its standard input to the remote command, the standard
+output of the remote command to its standard output, and the
+standard error of the remote command to its standard error.
+Interrupt, quit and terminate signals are propagated to the remote
+command;
+.Nm rsh
+normally terminates when the remote command does.
+The options are as follows:
+.Bl -tag -width flag
+.It Fl K
+The
+.Fl K
+option turns off all Kerberos authentication.
+.It Fl d
+The
+.Fl d
+option turns on socket debugging (using
+.Xr setsockopt  2  )
+on the
+.Tn TCP
+sockets used for communication with the remote host.
+.It Fl k
+The
+.Fl k
+option causes
+.Nm rsh
+to obtain tickets for the remote host in
+.Ar realm
+instead of the remote host's realm as determined by
+.Xr krb_realmofhost  3  .
+.It Fl l
+By default, the remote username is the same as the local username.
+The
+.Fl l
+option or the
+.Pa username@host
+format allow the remote name to be specified.
+Kerberos authentication is used, and authorization is determined
+as in
+.Xr rlogin  1  .
+.It Fl n
+The
+.Fl n
+option redirects input from the special device
+.Pa /dev/null
+(see the
+.Sx BUGS
+section of this manual page).
+.It Fl x
+The
+.Fl x
+option turns on
+.Tn DES
+encryption for all data exchange.
+This may introduce a significant delay in response time.
+.El
+.Pp
+If no
+.Ar command
+is specified, you will be logged in on the remote host using
+.Xr rlogin  1  .
+.Pp
+Shell metacharacters which are not quoted are interpreted on local machine,
+while quoted metacharacters are interpreted on the remote machine.
+For example, the command
+.Pp
+.Dl rsh otherhost cat remotefile >> localfile
+.Pp
+appends the remote file
+.Ar remotefile
+to the local file
+.Ar localfile ,
+while
+.Pp
+.Dl rsh otherhost cat remotefile \&">>\&" other_remotefile
+.Pp
+appends
+.Ar remotefile
+to
+.Ar other_remotefile .
+.\" .Pp
+.\" Many sites specify a large number of host names as commands in the
+.\" directory /usr/hosts.
+.\" If this directory is included in your search path, you can use the
+.\" shorthand ``host command'' for the longer form ``rsh host command''.
+.Sh FILES
+.Bl -tag -width /etc/hosts -compact
+.It Pa /etc/hosts
+.El
+.Sh SEE ALSO
+.Xr rlogin 1 ,
+.Xr kerberos 3 ,
+.Xr krb_sendauth 3 ,
+.Xr krb_realmofhost 3
+.Sh HISTORY
+The
+.Nm rsh
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+If you are using
+.Xr csh  1
+and put a
+.Nm rsh
+in the background without redirecting its input away from the terminal,
+it will block even if no reads are posted by the remote command.
+If no input is desired you should redirect the input of
+.Nm rsh
+to
+.Pa /dev/null
+using the
+.Fl n
+option.
+.Pp
+You cannot run an interactive command
+(like
+.Xr rogue  6
+or
+.Xr vi  1  )
+using
+.Nm rsh  ;
+use
+.Xr rlogin  1
+instead.
+.Pp
+Stop signals stop the local
+.Nm rsh
+process only; this is arguably wrong, but currently hard to fix for reasons
+too complicated to explain here.
diff --git a/rsh.tproj/rsh.c b/rsh.tproj/rsh.c
new file mode 100644 (file)
index 0000000..9474164
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1983, 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * $Source: /cvs/Darwin/Commands/NeXT/network_cmds/rsh.tproj/rsh.c,v $
+ * $Header: /cvs/Darwin/Commands/NeXT/network_cmds/rsh.tproj/rsh.c,v 1.1.1.1 1999/05/02 03:58:17 wsanchez Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <varargs.h>
+
+#include "pathnames.h"
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+CREDENTIALS cred;
+Key_schedule schedule;
+int use_kerberos = 1, doencrypt;
+char dst_realm_buf[REALM_SZ], *dest_realm;
+extern char *krb_realmofhost();
+#endif
+
+/*
+ * rsh - remote shell
+ */
+int    rfd2;
+
+char   *copyargs __P((char **));
+void   sendsig __P((int));
+void   talk __P((int, long, pid_t, int));
+void   usage __P((void));
+void   warning __P(());
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       struct passwd *pw;
+       struct servent *sp;
+       long omask;
+       int argoff, asrsh, ch, dflag, nflag, one, rem;
+       pid_t pid;
+       uid_t uid;
+       char *args, *host, *p, *user;
+
+       argoff = asrsh = dflag = nflag = 0;
+       one = 1;
+       host = user = NULL;
+
+       /* if called as something other than "rsh", use it as the host name */
+       if (p = strrchr(argv[0], '/'))
+               ++p;
+       else
+               p = argv[0];
+       if (strcmp(p, "rsh"))
+               host = p;
+       else
+               asrsh = 1;
+
+       /* handle "rsh host flags" */
+       if (!host && argc > 2 && argv[1][0] != '-') {
+               host = argv[1];
+               argoff = 1;
+       }
+
+#ifdef KERBEROS
+#ifdef CRYPT
+#define        OPTIONS "8KLdek:l:nwx"
+#else
+#define        OPTIONS "8KLdek:l:nw"
+#endif
+#else
+#define        OPTIONS "8KLdel:nw"
+#endif
+       while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
+               switch(ch) {
+               case 'K':
+#ifdef KERBEROS
+                       use_kerberos = 0;
+#endif
+                       break;
+               case 'L':       /* -8Lew are ignored to allow rlogin aliases */
+               case 'e':
+               case 'w':
+               case '8':
+                       break;
+               case 'd':
+                       dflag = 1;
+                       break;
+               case 'l':
+                       user = optarg;
+                       break;
+#ifdef KERBEROS
+               case 'k':
+                       dest_realm = dst_realm_buf;
+                       strncpy(dest_realm, optarg, REALM_SZ);
+                       break;
+#endif
+               case 'n':
+                       nflag = 1;
+                       break;
+#ifdef KERBEROS
+#ifdef CRYPT
+               case 'x':
+                       doencrypt = 1;
+                       des_set_key(cred.session, schedule);
+                       break;
+#endif
+#endif
+               case '?':
+               default:
+                       usage();
+               }
+       optind += argoff;
+
+       /* if haven't gotten a host yet, do so */
+       if (!host && !(host = argv[optind++]))
+               usage();
+
+       /* if no further arguments, must have been called as rlogin. */
+       if (!argv[optind]) {
+               if (asrsh)
+                       *argv = "rlogin";
+               execv(_PATH_RLOGIN, argv);
+               err(1, "can't exec %s", _PATH_RLOGIN);
+       }
+
+       argc -= optind;
+       argv += optind;
+
+       if (!(pw = getpwuid(uid = getuid())))
+               errx(1, "unknown user id");
+       /* Accept user1@host format, though "-l user2" overrides user1 */
+       p = strchr(host, '@');
+       if (p) {
+               *p = '\0';
+               if (!user && p > host)
+                       user = host;
+               host = p + 1;
+               if (*host == '\0')
+                       usage();
+       }
+       if (!user)
+               user = pw->pw_name;
+
+#ifdef KERBEROS
+#ifdef CRYPT
+       /* -x turns off -n */
+       if (doencrypt)
+               nflag = 0;
+#endif
+#endif
+
+       args = copyargs(argv);
+
+       sp = NULL;
+#ifdef KERBEROS
+       if (use_kerberos) {
+               sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
+               if (sp == NULL) {
+                       use_kerberos = 0;
+                       warning("can't get entry for %s/tcp service",
+                           doencrypt ? "ekshell" : "kshell");
+               }
+       }
+#endif
+       if (sp == NULL)
+               sp = getservbyname("shell", "tcp");
+       if (sp == NULL)
+               errx(1, "shell/tcp: unknown service");
+
+#ifdef KERBEROS
+try_connect:
+       if (use_kerberos) {
+               struct hostent *hp;
+
+               /* fully qualify hostname (needed for krb_realmofhost) */
+               hp = gethostbyname(host);
+               if (hp != NULL && !(host = strdup(hp->h_name)))
+                       err(1, NULL);
+
+               rem = KSUCCESS;
+               errno = 0;
+               if (dest_realm == NULL)
+                       dest_realm = krb_realmofhost(host);
+
+#ifdef CRYPT
+               if (doencrypt)
+                       rem = krcmd_mutual(&host, sp->s_port, user, args,
+                           &rfd2, dest_realm, &cred, schedule);
+               else
+#endif
+                       rem = krcmd(&host, sp->s_port, user, args, &rfd2,
+                           dest_realm);
+               if (rem < 0) {
+                       use_kerberos = 0;
+                       sp = getservbyname("shell", "tcp");
+                       if (sp == NULL)
+                               errx(1, "shell/tcp: unknown service");
+                       if (errno == ECONNREFUSED)
+                               warning("remote host doesn't support Kerberos");
+                       if (errno == ENOENT)
+                               warning("can't provide Kerberos auth data");
+                       goto try_connect;
+               }
+       } else {
+               if (doencrypt)
+                       errx(1, "the -x flag requires Kerberos authentication");
+               rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+       }
+#else
+       rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+#endif
+
+       if (rem < 0)
+               exit(1);
+
+       if (rfd2 < 0)
+               errx(1, "can't establish stderr");
+       if (dflag) {
+               if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
+                   sizeof(one)) < 0)
+                       warn("setsockopt");
+               if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
+                   sizeof(one)) < 0)
+                       warn("setsockopt");
+       }
+
+       (void)setuid(uid);
+       omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               (void)signal(SIGINT, sendsig);
+       if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+               (void)signal(SIGQUIT, sendsig);
+       if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+               (void)signal(SIGTERM, sendsig);
+
+       if (!nflag) {
+               pid = fork();
+               if (pid < 0)
+                       err(1, "fork");
+       }
+
+#ifdef KERBEROS
+#ifdef CRYPT
+       if (!doencrypt)
+#endif
+#endif
+       {
+               (void)ioctl(rfd2, FIONBIO, &one);
+               (void)ioctl(rem, FIONBIO, &one);
+       }
+
+       talk(nflag, omask, pid, rem);
+
+       if (!nflag)
+               (void)kill(pid, SIGKILL);
+       exit(0);
+}
+
+void
+talk(nflag, omask, pid, rem)
+       int nflag;
+       long omask;
+       pid_t pid;
+       int rem;
+{
+       int cc, wc;
+       fd_set readfrom, ready, rembits;
+       char *bp, buf[BUFSIZ];
+
+       if (!nflag && pid == 0) {
+               (void)close(rfd2);
+
+reread:                errno = 0;
+               if ((cc = read(0, buf, sizeof buf)) <= 0)
+                       goto done;
+               bp = buf;
+
+rewrite:       
+               FD_ZERO(&rembits);
+               FD_SET(rem, &rembits);
+               if (select(16, 0, &rembits, 0, 0) < 0) {
+                       if (errno != EINTR)
+                               err(1, "select");
+                       goto rewrite;
+               }
+               if (!FD_ISSET(rem, &rembits))
+                       goto rewrite;
+#ifdef KERBEROS
+#ifdef CRYPT
+               if (doencrypt)
+                       wc = des_write(rem, bp, cc);
+               else
+#endif
+#endif
+                       wc = write(rem, bp, cc);
+               if (wc < 0) {
+                       if (errno == EWOULDBLOCK)
+                               goto rewrite;
+                       goto done;
+               }
+               bp += wc;
+               cc -= wc;
+               if (cc == 0)
+                       goto reread;
+               goto rewrite;
+done:
+               (void)shutdown(rem, 1);
+               exit(0);
+       }
+
+       (void)sigsetmask(omask);
+       FD_ZERO(&readfrom);
+       FD_SET(rfd2, &readfrom);
+       FD_SET(rem, &readfrom);
+       do {
+               ready = readfrom;
+               if (select(16, &ready, 0, 0, 0) < 0) {
+                       if (errno != EINTR)
+                               err(1, "select");
+                       continue;
+               }
+               if (FD_ISSET(rfd2, &ready)) {
+                       errno = 0;
+#ifdef KERBEROS
+#ifdef CRYPT
+                       if (doencrypt)
+                               cc = des_read(rfd2, buf, sizeof buf);
+                       else
+#endif
+#endif
+                               cc = read(rfd2, buf, sizeof buf);
+                       if (cc <= 0) {
+                               if (errno != EWOULDBLOCK)
+                                       FD_CLR(rfd2, &readfrom);
+                       } else
+                               (void)write(2, buf, cc);
+               }
+               if (FD_ISSET(rem, &ready)) {
+                       errno = 0;
+#ifdef KERBEROS
+#ifdef CRYPT
+                       if (doencrypt)
+                               cc = des_read(rem, buf, sizeof buf);
+                       else
+#endif
+#endif
+                               cc = read(rem, buf, sizeof buf);
+                       if (cc <= 0) {
+                               if (errno != EWOULDBLOCK)
+                                       FD_CLR(rem, &readfrom);
+                       } else
+                               (void)write(1, buf, cc);
+               }
+       } while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom));
+}
+
+void
+sendsig(sig)
+       int sig;
+{
+       char signo;
+
+       signo = sig;
+#ifdef KERBEROS
+#ifdef CRYPT
+       if (doencrypt)
+               (void)des_write(rfd2, &signo, 1);
+       else
+#endif
+#endif
+               (void)write(rfd2, &signo, 1);
+}
+
+#ifdef KERBEROS
+/* VARARGS */
+void
+warning(va_alist)
+va_dcl
+{
+       va_list ap;
+       char *fmt;
+
+       (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
+       va_start(ap);
+       fmt = va_arg(ap, char *);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, ".\n");
+}
+#endif
+
+char *
+copyargs(argv)
+       char **argv;
+{
+       int cc;
+       char **ap, *args, *p;
+
+       cc = 0;
+       for (ap = argv; *ap; ++ap)
+               cc += strlen(*ap) + 1;
+       if (!(args = malloc((u_int)cc)))
+               err(1, NULL);
+       for (p = args, ap = argv; *ap; ++ap) {
+               (void)strcpy(p, *ap);
+               for (p = strcpy(p, *ap); *p; ++p);
+               if (ap[1])
+                       *p++ = ' ';
+       }
+       return (args);
+}
+
+void
+usage()
+{
+
+       (void)fprintf(stderr,
+           "usage: rsh [-nd%s]%s[-l login] [login@]host [command]\n",
+#ifdef KERBEROS
+#ifdef CRYPT
+           "x", " [-k realm] ");
+#else
+           "", " [-k realm] ");
+#endif
+#else
+           "", " ");
+#endif
+       exit(1);
+}
diff --git a/rshd.tproj/Makefile b/rshd.tproj/Makefile
new file mode 100644 (file)
index 0000000..3ebcdb8
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rshd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = rshd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rshd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rshd.tproj/Makefile.postamble b/rshd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..fd0e632
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
+VPATH += :../rlogin.tproj
+
diff --git a/rshd.tproj/Makefile.preamble b/rshd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..6301c77
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+OTHER_OFILES = des_rw.o
+
+-include ../Makefile.include
diff --git a/rshd.tproj/PB.project b/rshd.tproj/PB.project
new file mode 100644 (file)
index 0000000..1252083
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (rshd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rshd.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rshd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rshd.tproj/rshd.8 b/rshd.tproj/rshd.8
new file mode 100644 (file)
index 0000000..82e1991
--- /dev/null
@@ -0,0 +1,209 @@
+.\" Copyright (c) 1983, 1989, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)rshd.8     8.1 (Berkeley) 6/4/93
+.\"
+.Dd June 4, 1993
+.Dt RSHD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm rshd
+.Nd remote shell server
+.Sh SYNOPSIS
+.Nm rshd
+.Op Fl alnL
+.Sh DESCRIPTION
+The
+.Nm rshd
+server
+is the server for the 
+.Xr rcmd 3
+routine and, consequently, for the
+.Xr rsh 1
+program.  The server provides remote execution facilities
+with authentication based on privileged port numbers from trusted hosts.
+.Pp
+The
+.Nm rshd
+server
+listens for service requests at the port indicated in
+the ``cmd'' service specification; see
+.Xr services 5 .
+When a service request is received the following protocol
+is initiated:
+.Bl -enum
+.It
+The server checks the client's source port.
+If the port is not in the range 512-1023, the server
+aborts the connection.
+.It
+The server reads characters from the socket up
+to a null (`\e0') byte.  The resultant string is
+interpreted as an
+.Tn ASCII
+number, base 10.
+.It
+If the number received in step 2 is non-zero,
+it is interpreted as the port number of a secondary
+stream to be used for the 
+.Em stderr .
+A second connection is then created to the specified
+port on the client's machine.  The source port of this
+second connection is also in the range 512-1023.
+.It
+The server checks the client's source address
+and requests the corresponding host name (see
+.Xr gethostbyaddr 3 ,
+.Xr hosts 5
+and
+.Xr named 8 ) .
+If the hostname cannot be determined,
+the dot-notation representation of the host address is used.
+If the hostname is in the same domain as the server (according to
+the last two components of the domain name),
+or if the
+.Fl a
+option is given,
+the addresses for the hostname are requested,
+verifying that the name and address correspond.
+If address verification fails, the connection is aborted
+with the message, ``Host address mismatch.''
+.It
+A null terminated user name of at most 16 characters
+is retrieved on the initial socket.  This user name
+is interpreted as the user identity on the
+.Em client Ns 's
+machine.
+.It
+A null terminated user name of at most 16 characters
+is retrieved on the initial socket.  This user name
+is interpreted as a user identity to use on the
+.Sy server Ns 's
+machine.
+.It
+A null terminated command to be passed to a
+shell is retrieved on the initial socket.  The length of
+the command is limited by the upper bound on the size of
+the system's argument list.  
+.It
+.Nm Rshd
+then validates the user using
+.Xr ruserok 3 ,
+which uses the file
+.Pa /etc/hosts.equiv
+and the
+.Pa .rhosts
+file found in the user's home directory.  The
+.Fl l
+option prevents
+.Xr ruserok 3
+from doing any validation based on the user's ``.rhosts'' file,
+unless the user is the superuser.
+.It
+If the file 
+.Pa /etc/nologin
+exists and the user is not the superuser,
+the connection is closed.
+.It
+A null byte is returned on the initial socket
+and the command line is passed to the normal login
+shell of the user.  The
+shell inherits the network connections established
+by
+.Nm rshd .
+.El
+.Pp
+Transport-level keepalive messages are enabled unless the
+.Fl n
+option is present.
+The use of keepalive messages allows sessions to be timed out
+if the client crashes or becomes unreachable.
+.Pp
+The
+.Fl L
+option causes all successful accesses to be logged to
+.Xr syslogd 8
+as
+.Li auth.info
+messages.
+.Sh DIAGNOSTICS
+Except for the last one listed below,
+all diagnostic messages
+are returned on the initial socket,
+after which any network connections are closed.
+An error is indicated by a leading byte with a value of
+1 (0 is returned in step 10 above upon successful completion
+of all the steps prior to the execution of the login shell).
+.Bl -tag -width indent
+.It Sy Locuser too long.
+The name of the user on the client's machine is
+longer than 16 characters.
+.It Sy Ruser too long.
+The name of the user on the remote machine is
+longer than 16 characters.
+.It Sy Command too long  .
+The command line passed exceeds the size of the argument
+list (as configured into the system).
+.It Sy Login incorrect.
+No password file entry for the user name existed.
+.It Sy Remote directory.
+The 
+.Xr chdir
+command to the home directory failed.
+.It Sy Permission denied.
+The authentication procedure described above failed.
+.It Sy Can't make pipe.
+The pipe needed for the 
+.Em stderr ,
+wasn't created.
+.It Sy Can't fork; try again. 
+A
+.Xr fork
+by the server failed.
+.It Sy <shellname>: ...
+The user's login shell could not be started.  This message is returned
+on the connection associated with the
+.Em stderr ,
+and is not preceded by a flag byte.
+.El
+.Sh SEE ALSO
+.Xr rsh 1 ,
+.Xr rcmd 3 ,
+.Xr ruserok 3
+.Sh BUGS
+The authentication procedure used here assumes the integrity
+of each client machine and the connecting medium.  This is
+insecure, but is useful in an ``open'' environment.
+.Pp
+A facility to allow all data exchanges to be encrypted should be
+present.
+.Pp
+A more extensible protocol (such as Telnet) should be used.
diff --git a/rshd.tproj/rshd.c b/rshd.tproj/rshd.c
new file mode 100644 (file)
index 0000000..7e8d10c
--- /dev/null
@@ -0,0 +1,809 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1988, 1989, 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1989, 1992, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rshd.c     8.2 (Berkeley) 4/6/94";
+#endif /* not lint */
+
+/*
+ * remote shell server:
+ *     [port]\0
+ *     remuser\0
+ *     locuser\0
+ *     command\0
+ *     data
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+int    keepalive = 1;
+int    check_all;
+int    log_success;            /* If TRUE, log all successful accesses */
+int    sent_null;
+
+void    doit __P((struct sockaddr_in *));
+void    error __P((const char *, ...));
+void    getstr __P((char *, int, char *));
+int     local_domain __P((char *));
+char   *topdomain __P((char *));
+void    usage __P((void));
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#define        VERSION_SIZE    9
+#define SECURE_MESSAGE  "This rsh session is using DES encryption for all transmissions.\r\n"
+#define        OPTIONS         "alnkvxL"
+char   authbuf[sizeof(AUTH_DAT)];
+char   tickbuf[sizeof(KTEXT_ST)];
+int    doencrypt, use_kerberos, vacuous;
+Key_schedule   schedule;
+#else
+#define        OPTIONS "alnL"
+#endif
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern int __check_rhosts_file;
+       struct linger linger;
+       int ch, on = 1, fromlen;
+       struct sockaddr_in from;
+
+       openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+
+       opterr = 0;
+       while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
+               switch (ch) {
+               case 'a':
+                       check_all = 1;
+                       break;
+               case 'l':
+                       __check_rhosts_file = 0;
+                       break;
+               case 'n':
+                       keepalive = 0;
+                       break;
+#ifdef KERBEROS
+               case 'k':
+                       use_kerberos = 1;
+                       break;
+
+               case 'v':
+                       vacuous = 1;
+                       break;
+
+#ifdef CRYPT
+               case 'x':
+                       doencrypt = 1;
+                       break;
+#endif
+#endif
+               case 'L':
+                       log_success = 1;
+                       break;
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+
+       argc -= optind;
+       argv += optind;
+
+#ifdef KERBEROS
+       if (use_kerberos && vacuous) {
+               syslog(LOG_ERR, "only one of -k and -v allowed");
+               exit(2);
+       }
+#ifdef CRYPT
+       if (doencrypt && !use_kerberos) {
+               syslog(LOG_ERR, "-k is required for -x");
+               exit(2);
+       }
+#endif
+#endif
+
+       fromlen = sizeof (from);
+       if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+               syslog(LOG_ERR, "getpeername: %m");
+               _exit(1);
+       }
+       if (keepalive &&
+           setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
+           sizeof(on)) < 0)
+               syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+       linger.l_onoff = 1;
+       linger.l_linger = 60;                   /* XXX */
+       if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
+           sizeof (linger)) < 0)
+               syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
+       doit(&from);
+       /* NOTREACHED */
+}
+
+char   username[20] = "USER=";
+char   homedir[64] = "HOME=";
+char   shell[64] = "SHELL=";
+char   path[100] = "PATH=";
+char   *envinit[] =
+           {homedir, shell, path, username, 0};
+#ifdef __APPLE__
+extern
+#endif
+char   **environ;
+
+void
+doit(fromp)
+       struct sockaddr_in *fromp;
+{
+       extern char *__rcmd_errstr;     /* syslog hook from libc/net/rcmd.c. */
+       struct hostent *hp;
+       struct passwd *pwd;
+       u_short port;
+       fd_set ready, readfrom;
+       int cc, nfd, pv[2], pid, s;
+       int one = 1;
+       char *hostname, *errorstr, *errorhost;
+       char *cp, sig, buf[BUFSIZ];
+       char cmdbuf[NCARGS+1], locuser[16], remuser[16];
+       char remotehost[2 * MAXHOSTNAMELEN + 1];
+
+#ifdef KERBEROS
+       AUTH_DAT        *kdata = (AUTH_DAT *) NULL;
+       KTEXT           ticket = (KTEXT) NULL;
+       char            instance[INST_SZ], version[VERSION_SIZE];
+       struct          sockaddr_in     fromaddr;
+       int             rc;
+       long            authopts;
+       int             pv1[2], pv2[2];
+       fd_set          wready, writeto;
+
+       fromaddr = *fromp;
+#endif
+
+       (void) signal(SIGINT, SIG_DFL);
+       (void) signal(SIGQUIT, SIG_DFL);
+       (void) signal(SIGTERM, SIG_DFL);
+#ifdef DEBUG
+       { int t = open(_PATH_TTY, 2);
+         if (t >= 0) {
+               ioctl(t, TIOCNOTTY, (char *)0);
+               (void) close(t);
+         }
+       }
+#endif
+       fromp->sin_port = ntohs((u_short)fromp->sin_port);
+       if (fromp->sin_family != AF_INET) {
+               syslog(LOG_ERR, "malformed \"from\" address (af %d)",
+                   fromp->sin_family);
+               exit(1);
+       }
+#ifdef IP_OPTIONS
+      {
+       u_char optbuf[BUFSIZ/3], *cp;
+       char lbuf[BUFSIZ], *lp;
+       int optsize = sizeof(optbuf), ipproto;
+       struct protoent *ip;
+
+       if ((ip = getprotobyname("ip")) != NULL)
+               ipproto = ip->p_proto;
+       else
+               ipproto = IPPROTO_IP;
+       if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) &&
+           optsize != 0) {
+               lp = lbuf;
+               for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
+                       sprintf(lp, " %2.2x", *cp);
+               syslog(LOG_NOTICE,
+                   "Connection received from %s using IP options (ignored):%s",
+                   inet_ntoa(fromp->sin_addr), lbuf);
+               if (setsockopt(0, ipproto, IP_OPTIONS,
+                   (char *)NULL, optsize) != 0) {
+                       syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
+                       exit(1);
+               }
+       }
+      }
+#endif
+
+#ifdef KERBEROS
+       if (!use_kerberos)
+#endif
+               if (fromp->sin_port >= IPPORT_RESERVED ||
+                   fromp->sin_port < IPPORT_RESERVED/2) {
+                       syslog(LOG_NOTICE|LOG_AUTH,
+                           "Connection from %s on illegal port %u",
+                           inet_ntoa(fromp->sin_addr),
+                           fromp->sin_port);
+                       exit(1);
+               }
+
+       (void) alarm(60);
+       port = 0;
+       for (;;) {
+               char c;
+               if ((cc = read(STDIN_FILENO, &c, 1)) != 1) {
+                       if (cc < 0)
+                               syslog(LOG_NOTICE, "read: %m");
+                       shutdown(0, 1+1);
+                       exit(1);
+               }
+               if (c== 0)
+                       break;
+               port = port * 10 + c - '0';
+       }
+
+       (void) alarm(0);
+       if (port != 0) {
+               int lport = IPPORT_RESERVED - 1;
+               s = rresvport(&lport);
+               if (s < 0) {
+                       syslog(LOG_ERR, "can't get stderr port: %m");
+                       exit(1);
+               }
+#ifdef KERBEROS
+               if (!use_kerberos)
+#endif
+                       if (port >= IPPORT_RESERVED) {
+                               syslog(LOG_ERR, "2nd port not reserved");
+                               exit(1);
+                       }
+               fromp->sin_port = htons(port);
+               if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) {
+                       syslog(LOG_INFO, "connect second port %d: %m", port);
+                       exit(1);
+               }
+       }
+
+#ifdef KERBEROS
+       if (vacuous) {
+               error("rshd: remote host requires Kerberos authentication\n");
+               exit(1);
+       }
+#endif
+
+#ifdef notdef
+       /* from inetd, socket is already on 0, 1, 2 */
+       dup2(f, 0);
+       dup2(f, 1);
+       dup2(f, 2);
+#endif
+       errorstr = NULL;
+       hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
+               fromp->sin_family);
+       if (hp) {
+               /*
+                * If name returned by gethostbyaddr is in our domain,
+                * attempt to verify that we haven't been fooled by someone
+                * in a remote net; look up the name and check that this
+                * address corresponds to the name.
+                */
+               hostname = hp->h_name;
+#ifdef KERBEROS
+               if (!use_kerberos)
+#endif
+               if (check_all || local_domain(hp->h_name)) {
+                       strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
+                       remotehost[sizeof(remotehost) - 1] = 0;
+                       errorhost = remotehost;
+                       hp = gethostbyname(remotehost);
+                       if (hp == NULL) {
+                               syslog(LOG_INFO,
+                                   "Couldn't look up address for %s",
+                                   remotehost);
+                               errorstr =
+                               "Couldn't look up address for your host (%s)\n";
+                               hostname = inet_ntoa(fromp->sin_addr);
+                       } else for (; ; hp->h_addr_list++) {
+                               if (hp->h_addr_list[0] == NULL) {
+                                       syslog(LOG_NOTICE,
+                                         "Host addr %s not listed for host %s",
+                                           inet_ntoa(fromp->sin_addr),
+                                           hp->h_name);
+                                       errorstr =
+                                           "Host address mismatch for %s\n";
+                                       hostname = inet_ntoa(fromp->sin_addr);
+                                       break;
+                               }
+                               if (!bcmp(hp->h_addr_list[0],
+                                   (caddr_t)&fromp->sin_addr,
+                                   sizeof(fromp->sin_addr))) {
+                                       hostname = hp->h_name;
+                                       break;
+                               }
+                       }
+               }
+       } else
+               errorhost = hostname = inet_ntoa(fromp->sin_addr);
+
+#ifdef KERBEROS
+       if (use_kerberos) {
+               kdata = (AUTH_DAT *) authbuf;
+               ticket = (KTEXT) tickbuf;
+               authopts = 0L;
+               strcpy(instance, "*");
+               version[VERSION_SIZE - 1] = '\0';
+#ifdef CRYPT
+               if (doencrypt) {
+                       struct sockaddr_in local_addr;
+                       rc = sizeof(local_addr);
+                       if (getsockname(0, (struct sockaddr *)&local_addr,
+                           &rc) < 0) {
+                               syslog(LOG_ERR, "getsockname: %m");
+                               error("rshd: getsockname: %m");
+                               exit(1);
+                       }
+                       authopts = KOPT_DO_MUTUAL;
+                       rc = krb_recvauth(authopts, 0, ticket,
+                               "rcmd", instance, &fromaddr,
+                               &local_addr, kdata, "", schedule,
+                               version);
+                       des_set_key(kdata->session, schedule);
+               } else
+#endif
+                       rc = krb_recvauth(authopts, 0, ticket, "rcmd",
+                               instance, &fromaddr,
+                               (struct sockaddr_in *) 0,
+                               kdata, "", (bit_64 *) 0, version);
+               if (rc != KSUCCESS) {
+                       error("Kerberos authentication failure: %s\n",
+                                 krb_err_txt[rc]);
+                       exit(1);
+               }
+       } else
+#endif
+               getstr(remuser, sizeof(remuser), "remuser");
+
+       getstr(locuser, sizeof(locuser), "locuser");
+       getstr(cmdbuf, sizeof(cmdbuf), "command");
+       setpwent();
+       pwd = getpwnam(locuser);
+       if (pwd == NULL) {
+               syslog(LOG_INFO|LOG_AUTH,
+                   "%s@%s as %s: unknown login. cmd='%.80s'",
+                   remuser, hostname, locuser, cmdbuf);
+               if (errorstr == NULL)
+                       errorstr = "Login incorrect.\n";
+               goto fail;
+       }
+       if (chdir(pwd->pw_dir) < 0) {
+               (void) chdir("/");
+#ifdef notdef
+               syslog(LOG_INFO|LOG_AUTH,
+                   "%s@%s as %s: no home directory. cmd='%.80s'",
+                   remuser, hostname, locuser, cmdbuf);
+               error("No remote directory.\n");
+               exit(1);
+#endif
+       }
+
+#ifdef KERBEROS
+       if (use_kerberos) {
+               if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
+                       if (kuserok(kdata, locuser) != 0) {
+                               syslog(LOG_INFO|LOG_AUTH,
+                                   "Kerberos rsh denied to %s.%s@%s",
+                                   kdata->pname, kdata->pinst, kdata->prealm);
+                               error("Permission denied.\n");
+                               exit(1);
+                       }
+               }
+       } else
+#endif
+
+               if (errorstr ||
+                   pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
+                   iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0,
+                   remuser, locuser) < 0) {
+                       if (__rcmd_errstr)
+                               syslog(LOG_INFO|LOG_AUTH,
+                           "%s@%s as %s: permission denied (%s). cmd='%.80s'",
+                                   remuser, hostname, locuser, __rcmd_errstr,
+                                   cmdbuf);
+                       else
+                               syslog(LOG_INFO|LOG_AUTH,
+                           "%s@%s as %s: permission denied. cmd='%.80s'",
+                                   remuser, hostname, locuser, cmdbuf);
+fail:
+                       if (errorstr == NULL)
+                               errorstr = "Permission denied.\n";
+                       error(errorstr, errorhost);
+                       exit(1);
+               }
+
+       if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) {
+               error("Logins currently disabled.\n");
+               exit(1);
+       }
+
+       (void) write(STDERR_FILENO, "\0", 1);
+       sent_null = 1;
+
+       if (port) {
+               if (pipe(pv) < 0) {
+                       error("Can't make pipe.\n");
+                       exit(1);
+               }
+#ifdef CRYPT
+#ifdef KERBEROS
+               if (doencrypt) {
+                       if (pipe(pv1) < 0) {
+                               error("Can't make 2nd pipe.\n");
+                               exit(1);
+                       }
+                       if (pipe(pv2) < 0) {
+                               error("Can't make 3rd pipe.\n");
+                               exit(1);
+                       }
+               }
+#endif
+#endif
+               pid = fork();
+               if (pid == -1)  {
+                       error("Can't fork; try again.\n");
+                       exit(1);
+               }
+               if (pid) {
+#ifdef CRYPT
+#ifdef KERBEROS
+                       if (doencrypt) {
+                               static char msg[] = SECURE_MESSAGE;
+                               (void) close(pv1[1]);
+                               (void) close(pv2[1]);
+                               des_write(s, msg, sizeof(msg) - 1);
+
+                       } else
+#endif
+#endif
+                       {
+                               (void) close(0);
+                               (void) close(1);
+                       }
+                       (void) close(2);
+                       (void) close(pv[1]);
+
+                       FD_ZERO(&readfrom);
+                       FD_SET(s, &readfrom);
+                       FD_SET(pv[0], &readfrom);
+                       if (pv[0] > s)
+                               nfd = pv[0];
+                       else
+                               nfd = s;
+#ifdef CRYPT
+#ifdef KERBEROS
+                       if (doencrypt) {
+                               FD_ZERO(&writeto);
+                               FD_SET(pv2[0], &writeto);
+                               FD_SET(pv1[0], &readfrom);
+
+                               nfd = MAX(nfd, pv2[0]);
+                               nfd = MAX(nfd, pv1[0]);
+                       } else
+#endif
+#endif
+                               ioctl(pv[0], FIONBIO, (char *)&one);
+
+                       /* should set s nbio! */
+                       nfd++;
+                       do {
+                               ready = readfrom;
+#ifdef CRYPT
+#ifdef KERBEROS
+                               if (doencrypt) {
+                                       wready = writeto;
+                                       if (select(nfd, &ready,
+                                           &wready, (fd_set *) 0,
+                                           (struct timeval *) 0) < 0)
+                                               break;
+                               } else
+#endif
+#endif
+                                       if (select(nfd, &ready, (fd_set *)0,
+                                         (fd_set *)0, (struct timeval *)0) < 0)
+                                               break;
+                               if (FD_ISSET(s, &ready)) {
+                                       int     ret;
+#ifdef CRYPT
+#ifdef KERBEROS
+                                       if (doencrypt)
+                                               ret = des_read(s, &sig, 1);
+                                       else
+#endif
+#endif
+                                               ret = read(s, &sig, 1);
+                                       if (ret <= 0)
+                                               FD_CLR(s, &readfrom);
+                                       else
+                                               killpg(pid, sig);
+                               }
+                               if (FD_ISSET(pv[0], &ready)) {
+                                       errno = 0;
+                                       cc = read(pv[0], buf, sizeof(buf));
+                                       if (cc <= 0) {
+                                               shutdown(s, 1+1);
+                                               FD_CLR(pv[0], &readfrom);
+                                       } else {
+#ifdef CRYPT
+#ifdef KERBEROS
+                                               if (doencrypt)
+                                                       (void)
+                                                         des_write(s, buf, cc);
+                                               else
+#endif
+#endif
+                                                       (void)
+                                                         write(s, buf, cc);
+                                       }
+                               }
+#ifdef CRYPT
+#ifdef KERBEROS
+                               if (doencrypt && FD_ISSET(pv1[0], &ready)) {
+                                       errno = 0;
+                                       cc = read(pv1[0], buf, sizeof(buf));
+                                       if (cc <= 0) {
+                                               shutdown(pv1[0], 1+1);
+                                               FD_CLR(pv1[0], &readfrom);
+                                       } else
+                                               (void) des_write(STDOUT_FILENO,
+                                                   buf, cc);
+                               }
+
+                               if (doencrypt && FD_ISSET(pv2[0], &wready)) {
+                                       errno = 0;
+                                       cc = des_read(STDIN_FILENO,
+                                           buf, sizeof(buf));
+                                       if (cc <= 0) {
+                                               shutdown(pv2[0], 1+1);
+                                               FD_CLR(pv2[0], &writeto);
+                                       } else
+                                               (void) write(pv2[0], buf, cc);
+                               }
+#endif
+#endif
+
+                       } while (FD_ISSET(s, &readfrom) ||
+#ifdef CRYPT
+#ifdef KERBEROS
+                           (doencrypt && FD_ISSET(pv1[0], &readfrom)) ||
+#endif
+#endif
+                           FD_ISSET(pv[0], &readfrom));
+                       exit(0);
+               }
+               setpgrp(0, getpid());
+               (void) close(s);
+               (void) close(pv[0]);
+#ifdef CRYPT
+#ifdef KERBEROS
+               if (doencrypt) {
+                       close(pv1[0]); close(pv2[0]);
+                       dup2(pv1[1], 1);
+                       dup2(pv2[1], 0);
+                       close(pv1[1]);
+                       close(pv2[1]);
+               }
+#endif
+#endif
+               dup2(pv[1], 2);
+               close(pv[1]);
+       }
+       if (*pwd->pw_shell == '\0')
+               pwd->pw_shell = _PATH_BSHELL;
+#if    BSD > 43
+       if (setlogin(pwd->pw_name) < 0)
+               syslog(LOG_ERR, "setlogin() failed: %m");
+#endif
+       (void) setgid((gid_t)pwd->pw_gid);
+       initgroups(pwd->pw_name, pwd->pw_gid);
+       (void) setuid((uid_t)pwd->pw_uid);
+       environ = envinit;
+       strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
+       strcat(path, _PATH_DEFPATH);
+       strncat(shell, pwd->pw_shell, sizeof(shell)-7);
+       strncat(username, pwd->pw_name, sizeof(username)-6);
+       cp = strrchr(pwd->pw_shell, '/');
+       if (cp)
+               cp++;
+       else
+               cp = pwd->pw_shell;
+       endpwent();
+       if (log_success || pwd->pw_uid == 0) {
+#ifdef KERBEROS
+               if (use_kerberos)
+                   syslog(LOG_INFO|LOG_AUTH,
+                       "Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'",
+                       kdata->pname, kdata->pinst, kdata->prealm,
+                       hostname, locuser, cmdbuf);
+               else
+#endif
+                   syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",
+                       remuser, hostname, locuser, cmdbuf);
+       }
+       execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
+       perror(pwd->pw_shell);
+       exit(1);
+}
+
+/*
+ * Report error to client.  Note: can't be used until second socket has
+ * connected to client, or older clients will hang waiting for that
+ * connection first.
+ */
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+error(const char *fmt, ...)
+#else
+error(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+       int len;
+       char *bp, buf[BUFSIZ];
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       bp = buf;
+       if (sent_null == 0) {
+               *bp++ = 1;
+               len = 1;
+       } else
+               len = 0;
+       (void)vsnprintf(bp, sizeof(buf) - 1, fmt, ap);
+       (void)write(STDERR_FILENO, buf, len + strlen(bp));
+}
+
+void
+getstr(buf, cnt, err)
+       char *buf, *err;
+       int cnt;
+{
+       char c;
+
+       do {
+               if (read(STDIN_FILENO, &c, 1) != 1)
+                       exit(1);
+               *buf++ = c;
+               if (--cnt == 0) {
+                       error("%s too long\n", err);
+                       exit(1);
+               }
+       } while (c != 0);
+}
+
+/*
+ * Check whether host h is in our local domain,
+ * defined as sharing the last two components of the domain part,
+ * or the entire domain part if the local domain has only one component.
+ * If either name is unqualified (contains no '.'),
+ * assume that the host is local, as it will be
+ * interpreted as such.
+ */
+int
+local_domain(h)
+       char *h;
+{
+       char localhost[MAXHOSTNAMELEN];
+       char *p1, *p2;
+
+       localhost[0] = 0;
+       (void) gethostname(localhost, sizeof(localhost));
+       p1 = topdomain(localhost);
+       p2 = topdomain(h);
+       if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
+               return (1);
+       return (0);
+}
+
+char *
+topdomain(h)
+       char *h;
+{
+       char *p, *maybe = NULL;
+       int dots = 0;
+
+       for (p = h + strlen(h); p >= h; p--) {
+               if (*p == '.') {
+                       if (++dots == 2)
+                               return (p);
+                       maybe = p;
+               }
+       }
+       return (maybe);
+}
+
+void
+usage()
+{
+
+       syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS);
+       exit(2);
+}
diff --git a/ruptime.tproj/Makefile b/ruptime.tproj/Makefile
new file mode 100644 (file)
index 0000000..09c2040
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ruptime
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ruptime.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
+            h.template ruptime.1 Makefile.dist
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ruptime.tproj/Makefile.dist b/ruptime.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..57f1e15
--- /dev/null
@@ -0,0 +1,5 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/6/93
+
+PROG=  ruptime
+
+.include <bsd.prog.mk>
diff --git a/ruptime.tproj/Makefile.postamble b/ruptime.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7823726
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/ruptime.tproj/Makefile.preamble b/ruptime.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/ruptime.tproj/PB.project b/ruptime.tproj/PB.project
new file mode 100644 (file)
index 0000000..f086f24
--- /dev/null
@@ -0,0 +1,35 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (ruptime.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            m.template, 
+            h.template, 
+            ruptime.1, 
+            Makefile.dist
+        ); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ruptime; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ruptime.tproj/h.template b/ruptime.tproj/h.template
new file mode 100644 (file)
index 0000000..f3c1b04
--- /dev/null
@@ -0,0 +1,11 @@
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
diff --git a/ruptime.tproj/m.template b/ruptime.tproj/m.template
new file mode 100644 (file)
index 0000000..1216fe5
--- /dev/null
@@ -0,0 +1,18 @@
+$$ Lines starting with $$ are not inserted into newly created files
+$$ The following substitutions are made:
+$$
+$$ $FILENAME$                e.g. foo.m
+$$ $FILENAMESANSEXTENSION$   e.g. foo
+$$ $DIRECTORY$               e.g. /tmp/MyNewApp
+$$ $PROJECTNAME$             e.g. MyNewApp
+$$ $SUBPROJECTNAME$          e.g. TheGoodPart.subproj
+$$ $USERNAME$                e.g. mwagner
+$$ $DATE$                    e.g. Jan-1-1994
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import "$FILENAMESANSEXTENSION$.h"
+
+@implementation $FILENAMESANSEXTENSION$
+
+@end
diff --git a/ruptime.tproj/ruptime.1 b/ruptime.tproj/ruptime.1
new file mode 100644 (file)
index 0000000..b3b0af8
--- /dev/null
@@ -0,0 +1,81 @@
+.\" Copyright (c) 1983, 1990, 1993, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)ruptime.1  8.2 (Berkeley) 4/5/94
+.\"
+.Dd April 5, 1994
+.Dt RUPTIME 1
+.Os BSD 4.2
+.Sh NAME
+.Nm ruptime
+.Nd show host status of local machines
+.Sh SYNOPSIS
+.Nm ruptime
+.Op Fl alrtu
+.Sh DESCRIPTION
+.Nm Ruptime
+gives a status line like
+.Ar uptime
+for each machine on the local network; these are formed from packets
+broadcast by each host on the network once a minute.
+.Pp
+Machines for which no status report has been received for 11
+minutes are shown as being down.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Users idle an hour or more are not counted unless the
+.Fl a
+flag is given.
+.It Fl l
+Sort by load average.
+.It Fl r
+Reverses the sort order.
+.It Fl t
+Sort by uptime.
+.It Fl u
+Sort by number of users.
+.El
+.Pp
+The default listing is sorted by host name.
+.Sh FILES
+.Bl -tag -width /var/rwho/whod.* -compact
+.It Pa /var/rwho/whod.*
+data files
+.El
+.Sh SEE ALSO
+.Xr rwho 1
+.Xr uptime 1
+.Sh HISTORY
+.Nm Ruptime
+appeared in
+.Bx 4.2 .
diff --git a/ruptime.tproj/ruptime.c b/ruptime.tproj/ruptime.c
new file mode 100644 (file)
index 0000000..e6cb457
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <protocols/rwhod.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <tzfile.h>
+#include <unistd.h>
+
+struct hs {
+       struct  whod *hs_wd;
+       int     hs_nusers;
+} *hs;
+struct whod awhod;
+
+#define        ISDOWN(h)               (now - (h)->hs_wd->wd_recvtime > 11 * 60)
+#define        WHDRSIZE        (sizeof (awhod) - sizeof (awhod.wd_we))
+
+size_t nhosts;
+time_t now;
+int rflg = 1;
+
+int     hscmp __P((const void *, const void *));
+char   *interval __P((time_t, char *));
+int     lcmp __P((const void *, const void *));
+void    morehosts __P((void));
+int     tcmp __P((const void *, const void *));
+int     ucmp __P((const void *, const void *));
+void    usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern int optind;
+       struct dirent *dp;
+       struct hs *hsp;
+       struct whod *wd;
+       struct whoent *we;
+       DIR *dirp;
+       size_t hspace;
+       int aflg, cc, ch, fd, i, maxloadav;
+       char buf[sizeof(struct whod)];
+       int (*cmp) __P((const void *, const void *));
+
+       aflg = 0;
+       cmp = hscmp;
+       while ((ch = getopt(argc, argv, "alrut")) != EOF)
+               switch (ch) {
+               case 'a':
+                       aflg = 1;
+                       break;
+               case 'l':
+                       cmp = lcmp;
+                       break;
+               case 'r':
+                       rflg = -1;
+                       break;
+               case 't':
+                       cmp = tcmp;
+                       break;
+               case 'u':
+                       cmp = ucmp;
+                       break;
+               default: 
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 0)
+               usage();
+
+       if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
+               err(1, "%s", _PATH_RWHODIR);
+
+       maxloadav = -1;
+       for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) {
+               if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
+                       continue;
+               if ((fd = open(dp->d_name, O_RDONLY, 0)) < 0) {
+                       warn("%s", dp->d_name);
+                       continue;
+               }
+               cc = read(fd, buf, sizeof(struct whod));
+               (void)close(fd);
+
+               if (cc < WHDRSIZE)
+                       continue;
+               if (nhosts == hspace) {
+                       if ((hs =
+                           realloc(hs, (hspace += 40) * sizeof(*hs))) == NULL)
+                               err(1, NULL);
+                       hsp = hs + nhosts;
+               }
+
+               if ((hsp->hs_wd = malloc((size_t)WHDRSIZE)) == NULL)
+                       err(1, NULL);
+               memmove(hsp->hs_wd, buf, (size_t)WHDRSIZE);
+
+               for (wd = (struct whod *)buf, i = 0; i < 2; ++i)
+                       if (wd->wd_loadav[i] > maxloadav)
+                               maxloadav = wd->wd_loadav[i];
+
+               for (hsp->hs_nusers = 0,
+                   we = (struct whoent *)(buf + cc); --we >= wd->wd_we;)
+                       if (aflg || we->we_idle < 3600)
+                               ++hsp->hs_nusers;
+               ++hsp;
+               ++nhosts;
+       }
+       if (nhosts == 0)
+               errx(0, "no hosts in %s.", _PATH_RWHODIR);
+
+       (void)time(&now);
+       qsort(hs, nhosts, sizeof(hs[0]), cmp);
+       for (i = 0; i < nhosts; i++) {
+               hsp = &hs[i];
+               if (ISDOWN(hsp)) {
+                       (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
+                           interval(now - hsp->hs_wd->wd_recvtime, "down"));
+                       continue;
+               }
+               (void)printf(
+                   "%-12.12s%s,  %4d user%s  load %*.2f, %*.2f, %*.2f\n",
+                   hsp->hs_wd->wd_hostname,
+                   interval((time_t)hsp->hs_wd->wd_sendtime -
+                       (time_t)hsp->hs_wd->wd_boottime, "  up"),
+                   hsp->hs_nusers,
+                   hsp->hs_nusers == 1 ? ", " : "s,",
+                   maxloadav >= 1000 ? 5 : 4,
+                       hsp->hs_wd->wd_loadav[0] / 100.0,
+                   maxloadav >= 1000 ? 5 : 4,
+                       hsp->hs_wd->wd_loadav[1] / 100.0,
+                   maxloadav >= 1000 ? 5 : 4,
+                       hsp->hs_wd->wd_loadav[2] / 100.0);
+       }
+       exit(0);
+}
+
+char *
+interval(tval, updown)
+       time_t tval;
+       char *updown;
+{
+       static char resbuf[32];
+       int days, hours, minutes;
+
+       if (tval < 0 || tval > DAYSPERNYEAR * SECSPERDAY) {
+               (void)snprintf(resbuf, sizeof(resbuf), "   %s ??:??", updown);
+               return (resbuf);
+       }
+                                               /* round to minutes. */
+       minutes = (tval + (SECSPERMIN - 1)) / SECSPERMIN;
+       hours = minutes / MINSPERHOUR;
+       minutes %= MINSPERHOUR;
+       days = hours / HOURSPERDAY;
+       hours %= HOURSPERDAY;
+       if (days)
+               (void)snprintf(resbuf, sizeof(resbuf),
+                   "%s %2d+%02d:%02d", updown, days, hours, minutes);
+       else
+               (void)snprintf(resbuf, sizeof(resbuf),
+                   "%s    %2d:%02d", updown, hours, minutes);
+       return (resbuf);
+}
+
+#define        HS(a)   ((struct hs *)(a))
+
+/* Alphabetical comparison. */
+int
+hscmp(a1, a2)
+       const void *a1, *a2;
+{
+       return (rflg *
+           strcmp(HS(a1)->hs_wd->wd_hostname, HS(a2)->hs_wd->wd_hostname));
+}
+
+/* Load average comparison. */
+int
+lcmp(a1, a2)
+       const void *a1, *a2;
+{
+       if (ISDOWN(HS(a1)))
+               if (ISDOWN(HS(a2)))
+                       return (tcmp(a1, a2));
+               else
+                       return (rflg);
+       else if (ISDOWN(HS(a2)))
+               return (-rflg);
+       else
+               return (rflg *
+                  (HS(a2)->hs_wd->wd_loadav[0] - HS(a1)->hs_wd->wd_loadav[0]));
+}
+
+/* Number of users comparison. */
+int
+ucmp(a1, a2)
+       const void *a1, *a2;
+{
+       if (ISDOWN(HS(a1)))
+               if (ISDOWN(HS(a2)))
+                       return (tcmp(a1, a2));
+               else
+                       return (rflg);
+       else if (ISDOWN(HS(a2)))
+               return (-rflg);
+       else
+               return (rflg * (HS(a2)->hs_nusers - HS(a1)->hs_nusers));
+}
+
+/* Uptime comparison. */
+int
+tcmp(a1, a2)
+       const void *a1, *a2;
+{
+       return (rflg * (
+               (ISDOWN(HS(a2)) ? HS(a2)->hs_wd->wd_recvtime - now
+                   : HS(a2)->hs_wd->wd_sendtime - HS(a2)->hs_wd->wd_boottime)
+               -
+               (ISDOWN(HS(a1)) ? HS(a1)->hs_wd->wd_recvtime - now
+                   : HS(a1)->hs_wd->wd_sendtime - HS(a1)->hs_wd->wd_boottime)
+       ));
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr, "usage: ruptime [-alrut]\n");
+       exit(1);
+}
diff --git a/rwho.tproj/Makefile b/rwho.tproj/Makefile
new file mode 100644 (file)
index 0000000..ac0d8cb
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rwho
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = rwho.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rwho.1\
+            Makefile.dist
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rwho.tproj/Makefile.dist b/rwho.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..328aa38
--- /dev/null
@@ -0,0 +1,5 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/6/93
+
+PROG=  rwho
+
+.include <bsd.prog.mk>
diff --git a/rwho.tproj/Makefile.postamble b/rwho.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7823726
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/rwho.tproj/Makefile.preamble b/rwho.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/rwho.tproj/PB.project b/rwho.tproj/PB.project
new file mode 100644 (file)
index 0000000..8a18feb
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (rwho.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rwho.1, Makefile.dist); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rwho; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rwho.tproj/rwho.1 b/rwho.tproj/rwho.1
new file mode 100644 (file)
index 0000000..f039b01
--- /dev/null
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)rwho.1     8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt RWHO 1
+.Os BSD 4.2
+.Sh NAME
+.Nm rwho
+.Nd who is logged in on local machines
+.Sh SYNOPSIS
+.Nm rwho
+.Op Fl a
+.Sh DESCRIPTION
+The
+.Nm rwho
+command produces output similar to
+.Xr who ,
+but for all machines on the local network.
+If no report has been
+received from a machine for 5 minutes then
+.Nm rwho
+assumes the machine is down, and does not report users last known
+to be logged into that machine.
+.Pp
+If a users hasn't typed to the system for a minute or more, then
+.Nm rwho
+reports this idle time.  If a user hasn't typed to the system for
+an hour or more, then
+the user will be omitted from the output of
+.Nm rwho
+unless the
+.Fl a
+flag is given.
+.Sh FILES
+.Bl -tag -width /var/rwho/rhowd.* -compact
+.It Pa /var/rwho/whod.*
+information about other machines
+.El
+.Sh SEE ALSO
+.Xr ruptime 1 ,
+.Xr rwhod 8
+.Sh HISTORY
+The
+.Nm rwho
+command
+appeared in
+.Bx 4.3 .
+.Sh BUGS
+This is unwieldy when the number of machines
+on the local net is large.
diff --git a/rwho.tproj/rwho.c b/rwho.tproj/rwho.c
new file mode 100644 (file)
index 0000000..815f13a
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <protocols/rwhod.h>
+#include <stdio.h>
+
+DIR    *dirp;
+
+struct whod wd;
+int    utmpcmp();
+#define        NUSERS  1000
+struct myutmp {
+       char    myhost[MAXHOSTNAMELEN];
+       int     myidle;
+       struct  outmp myutmp;
+} myutmp[NUSERS];
+int    nusers;
+
+#define        WHDRSIZE        (sizeof (wd) - sizeof (wd.wd_we))
+/* 
+ * this macro should be shared with ruptime.
+ */
+#define        down(w,now)     ((now) - (w)->wd_recvtime > 11 * 60)
+
+char   *ctime(), *strcpy();
+time_t now;
+int    aflg;
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern char *optarg;
+       extern int optind;
+       int ch;
+       struct direct *dp;
+       int cc, width;
+       register struct whod *w = &wd;
+       register struct whoent *we;
+       register struct myutmp *mp;
+       int f, n, i;
+       time_t time();
+
+       while ((ch = getopt(argc, argv, "a")) != EOF)
+               switch((char)ch) {
+               case 'a':
+                       aflg = 1;
+                       break;
+               case '?':
+               default:
+                       fprintf(stderr, "usage: rwho [-a]\n");
+                       exit(1);
+               }
+       if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) {
+               perror(_PATH_RWHODIR);
+               exit(1);
+       }
+       mp = myutmp;
+       (void)time(&now);
+       while (dp = readdir(dirp)) {
+               if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
+                       continue;
+               f = open(dp->d_name, O_RDONLY);
+               if (f < 0)
+                       continue;
+               cc = read(f, (char *)&wd, sizeof (struct whod));
+               if (cc < WHDRSIZE) {
+                       (void) close(f);
+                       continue;
+               }
+               if (down(w,now)) {
+                       (void) close(f);
+                       continue;
+               }
+               cc -= WHDRSIZE;
+               we = w->wd_we;
+               for (n = cc / sizeof (struct whoent); n > 0; n--) {
+                       if (aflg == 0 && we->we_idle >= 60*60) {
+                               we++;
+                               continue;
+                       }
+                       if (nusers >= NUSERS) {
+                               printf("too many users\n");
+                               exit(1);
+                       }
+                       mp->myutmp = we->we_utmp; mp->myidle = we->we_idle;
+                       (void) strcpy(mp->myhost, w->wd_hostname);
+                       nusers++; we++; mp++;
+               }
+               (void) close(f);
+       }
+       qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp);
+       mp = myutmp;
+       width = 0;
+       for (i = 0; i < nusers; i++) {
+               int j = strlen(mp->myhost) + 1 + strlen(mp->myutmp.out_line);
+               if (j > width)
+                       width = j;
+               mp++;
+       }
+       mp = myutmp;
+       for (i = 0; i < nusers; i++) {
+               char buf[BUFSIZ];
+               (void)sprintf(buf, "%s:%s", mp->myhost, mp->myutmp.out_line);
+               printf("%-8.8s %-*s %.12s",
+                  mp->myutmp.out_name,
+                  width,
+                  buf,
+                  ctime((time_t *)&mp->myutmp.out_time)+4);
+               mp->myidle /= 60;
+               if (mp->myidle) {
+                       if (aflg) {
+                               if (mp->myidle >= 100*60)
+                                       mp->myidle = 100*60 - 1;
+                               if (mp->myidle >= 60)
+                                       printf(" %2d", mp->myidle / 60);
+                               else
+                                       printf("   ");
+                       } else
+                               printf(" ");
+                       printf(":%02d", mp->myidle % 60);
+               }
+               printf("\n");
+               mp++;
+       }
+       exit(0);
+}
+
+utmpcmp(u1, u2)
+       struct myutmp *u1, *u2;
+{
+       int rc;
+
+       rc = strncmp(u1->myutmp.out_name, u2->myutmp.out_name, 8);
+       if (rc)
+               return (rc);
+       rc = strncmp(u1->myhost, u2->myhost, 8);
+       if (rc)
+               return (rc);
+       return (strncmp(u1->myutmp.out_line, u2->myutmp.out_line, 8));
+}
diff --git a/rwhod.tproj/Makefile b/rwhod.tproj/Makefile
new file mode 100644 (file)
index 0000000..fc4f54b
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = rwhod
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = rwhod.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rwhod.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/rwhod.tproj/Makefile.postamble b/rwhod.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..f5c79e2
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
diff --git a/rwhod.tproj/Makefile.preamble b/rwhod.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2c9003c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/rwhod.tproj/PB.project b/rwhod.tproj/PB.project
new file mode 100644 (file)
index 0000000..9329dd8
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (rwhod.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rwhod.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = rwhod; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/rwhod.tproj/rwhod.8 b/rwhod.tproj/rwhod.8
new file mode 100644 (file)
index 0000000..4b8492e
--- /dev/null
@@ -0,0 +1,146 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)rwhod.8    8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt RWHOD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm rwhod
+.Nd system status server
+.Sh SYNOPSIS
+.Nm rwhod
+.Sh DESCRIPTION
+.Nm Rwhod
+is the server which maintains the database used by the
+.Xr rwho 1
+and
+.Xr ruptime 1
+programs.  Its operation is predicated on the ability to
+.Em broadcast
+messages on a network.
+.Pp
+.Nm Rwhod
+operates as both a producer and consumer of status information.
+As a producer of information it periodically
+queries the state of the system and constructs
+status messages which are broadcast on a network.
+As a consumer of information, it listens for other
+.Nm rwhod
+servers' status messages, validating them, then recording
+them in a collection of files located in the directory
+.Pa /var/rwho .
+.Pp
+The server transmits and receives messages at the port indicated
+in the ``rwho'' service specification; see 
+.Xr services 5 .
+The messages sent and received, are of the form:
+.Bd -literal -offset indent
+struct outmp {
+       char    out_line[8];            /* tty name */
+       char    out_name[8];            /* user id */
+       long    out_time;               /* time on */
+};
+
+struct whod {
+       char    wd_vers;
+       char    wd_type;
+       char    wd_fill[2];
+       int     wd_sendtime;
+       int     wd_recvtime;
+       char    wd_hostname[32];
+       int     wd_loadav[3];
+       int     wd_boottime;
+       struct  whoent {
+               struct  outmp we_utmp;
+               int     we_idle;
+       } wd_we[1024 / sizeof (struct whoent)];
+};
+.Ed
+.Pp
+All fields are converted to network byte order prior to
+transmission.  The load averages are as calculated by the
+.Xr w 1
+program, and represent load averages over the 5, 10, and 15 minute 
+intervals prior to a server's transmission; they are multiplied by 100
+for representation in an integer.  The host name
+included is that returned by the
+.Xr gethostname 2
+system call, with any trailing domain name omitted.
+The array at the end of the message contains information about
+the users logged in to the sending machine.  This information 
+includes the contents of the 
+.Xr utmp 5
+entry for each non-idle terminal line and a value indicating the
+time in seconds since a character was last received on the terminal line.
+.Pp
+Messages received by the
+.Xr rwho
+server are discarded unless they originated at an
+.Xr rwho
+server's port.  In addition, if the host's name, as specified
+in the message, contains any unprintable
+.Tn ASCII
+characters, the
+message is discarded.  Valid messages received by
+.Nm rwhod
+are placed in files named
+.Pa whod.hostname
+in the directory
+.Pa /var/rwho .
+These files contain only the most recent message, in the
+format described above.
+.Pp
+Status messages are generated approximately once every
+3 minutes.
+.Nm Rwhod
+performs an
+.Xr nlist 3
+on
+.Pa /vmunix
+every 30 minutes to guard against
+the possibility that this file is not the system
+image currently operating.
+.Sh SEE ALSO
+.Xr rwho 1 ,
+.Xr ruptime 1
+.Sh BUGS
+There should be a way to relay status information between networks. 
+Status information should be sent only upon request rather than continuously.
+People often interpret the server dying
+or network communication failures
+as a machine going down.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/rwhod.tproj/rwhod.c b/rwhod.tproj/rwhod.c
new file mode 100644 (file)
index 0000000..6094340
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rwhod.c    8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <protocols/rwhod.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <utmp.h>
+
+/*
+ * Alarm interval. Don't forget to change the down time check in ruptime
+ * if this is changed.
+ */
+#define AL_INTERVAL (3 * 60)
+
+char   myname[MAXHOSTNAMELEN];
+
+/*
+ * We communicate with each neighbor in a list constructed at the time we're
+ * started up.  Neighbors are currently directly connected via a hardware
+ * interface.
+ */
+struct neighbor {
+       struct  neighbor *n_next;
+       char    *n_name;                /* interface name */
+       struct  sockaddr *n_addr;               /* who to send to */
+       int     n_addrlen;              /* size of address */
+       int     n_flags;                /* should forward?, interface flags */
+};
+
+struct neighbor *neighbors;
+struct whod mywd;
+struct servent *sp;
+int    s, utmpf;
+
+#define        WHDRSIZE        (sizeof(mywd) - sizeof(mywd.wd_we))
+
+int     configure __P((int));
+void    getboottime __P((int));
+void    onalrm __P((int));
+void    quit __P((char *));
+void    rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
+int     verify __P((char *));
+#ifdef DEBUG
+char   *interval __P((int, char *));
+void    Sendto __P((int, char *, int, int, char *, int));
+#define         sendto Sendto
+#endif
+
+int
+main(argc, argv)
+       int argc;
+       char argv[];
+{
+       struct sockaddr_in from;
+       struct stat st;
+       char path[64];
+       int on = 1;
+       char *cp;
+       struct sockaddr_in sin;
+
+       if (getuid()) {
+               fprintf(stderr, "rwhod: not super user\n");
+               exit(1);
+       }
+       sp = getservbyname("who", "udp");
+       if (sp == NULL) {
+               fprintf(stderr, "rwhod: udp/who: unknown service\n");
+               exit(1);
+       }
+#ifndef DEBUG
+       daemon(1, 0);
+#endif
+       if (chdir(_PATH_RWHODIR) < 0) {
+               (void)fprintf(stderr, "rwhod: %s: %s\n",
+                   _PATH_RWHODIR, strerror(errno));
+               exit(1);
+       }
+       (void) signal(SIGHUP, getboottime);
+       openlog("rwhod", LOG_PID, LOG_DAEMON);
+       /*
+        * Establish host name as returned by system.
+        */
+       if (gethostname(myname, sizeof(myname) - 1) < 0) {
+               syslog(LOG_ERR, "gethostname: %m");
+               exit(1);
+       }
+       if ((cp = index(myname, '.')) != NULL)
+               *cp = '\0';
+       strncpy(mywd.wd_hostname, myname, sizeof(myname) - 1);
+       utmpf = open(_PATH_UTMP, O_RDONLY|O_CREAT, 0644);
+       if (utmpf < 0) {
+               syslog(LOG_ERR, "%s: %m", _PATH_UTMP);
+               exit(1);
+       }
+       getboottime(0);
+       if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               syslog(LOG_ERR, "socket: %m");
+               exit(1);
+       }
+       if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
+               syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+               exit(1);
+       }
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = sp->s_port;
+       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+               syslog(LOG_ERR, "bind: %m");
+               exit(1);
+       }
+       if (!configure(s))
+               exit(1);
+       signal(SIGALRM, onalrm);
+       onalrm(0);
+       for (;;) {
+               struct whod wd;
+               int cc, whod, len = sizeof(from);
+
+               cc = recvfrom(s, (char *)&wd, sizeof(struct whod), 0,
+                       (struct sockaddr *)&from, &len);
+               if (cc <= 0) {
+                       if (cc < 0 && errno != EINTR)
+                               syslog(LOG_WARNING, "recv: %m");
+                       continue;
+               }
+               if (from.sin_port != sp->s_port) {
+                       syslog(LOG_WARNING, "%d: bad from port",
+                               ntohs(from.sin_port));
+                       continue;
+               }
+               if (wd.wd_vers != WHODVERSION)
+                       continue;
+               if (wd.wd_type != WHODTYPE_STATUS)
+                       continue;
+               if (!verify(wd.wd_hostname)) {
+                       syslog(LOG_WARNING, "malformed host name from %x",
+                               from.sin_addr);
+                       continue;
+               }
+               (void) sprintf(path, "whod.%s", wd.wd_hostname);
+               /*
+                * Rather than truncating and growing the file each time,
+                * use ftruncate if size is less than previous size.
+                */
+               whod = open(path, O_WRONLY | O_CREAT, 0644);
+               if (whod < 0) {
+                       syslog(LOG_WARNING, "%s: %m", path);
+                       continue;
+               }
+#if ENDIAN != BIG_ENDIAN
+               {
+                       int i, n = (cc - WHDRSIZE)/sizeof(struct whoent);
+                       struct whoent *we;
+
+                       /* undo header byte swapping before writing to file */
+                       wd.wd_sendtime = ntohl(wd.wd_sendtime);
+                       for (i = 0; i < 3; i++)
+                               wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]);
+                       wd.wd_boottime = ntohl(wd.wd_boottime);
+                       we = wd.wd_we;
+                       for (i = 0; i < n; i++) {
+                               we->we_idle = ntohl(we->we_idle);
+                               we->we_utmp.out_time =
+                                   ntohl(we->we_utmp.out_time);
+                               we++;
+                       }
+               }
+#endif
+               (void) time((time_t *)&wd.wd_recvtime);
+               (void) write(whod, (char *)&wd, cc);
+               if (fstat(whod, &st) < 0 || st.st_size > cc)
+                       ftruncate(whod, cc);
+               (void) close(whod);
+       }
+}
+
+/*
+ * Check out host name for unprintables
+ * and other funnies before allowing a file
+ * to be created.  Sorry, but blanks aren't allowed.
+ */
+int
+verify(name)
+       register char *name;
+{
+       register int size = 0;
+
+       while (*name) {
+               if (!isascii(*name) || !(isalnum(*name) || ispunct(*name)))
+                       return (0);
+               name++, size++;
+       }
+       return (size > 0);
+}
+
+int    utmptime;
+int    utmpent;
+int    utmpsize = 0;
+struct utmp *utmp;
+int    alarmcount;
+
+void
+onalrm(signo)
+       int signo;
+{
+       register struct neighbor *np;
+       register struct whoent *we = mywd.wd_we, *wlast;
+       register int i;
+       struct stat stb;
+       double avenrun[3];
+       time_t now;
+       int cc;
+
+       now = time(NULL);
+       if (alarmcount % 10 == 0)
+               getboottime(0);
+       alarmcount++;
+       (void) fstat(utmpf, &stb);
+       if ((stb.st_mtime != utmptime) || (stb.st_size > utmpsize)) {
+               utmptime = stb.st_mtime;
+               if (stb.st_size > utmpsize) {
+                       utmpsize = stb.st_size + 10 * sizeof(struct utmp);
+                       if (utmp)
+                               utmp = (struct utmp *)realloc(utmp, utmpsize);
+                       else
+                               utmp = (struct utmp *)malloc(utmpsize);
+                       if (! utmp) {
+                               fprintf(stderr, "rwhod: malloc failed\n");
+                               utmpsize = 0;
+                               goto done;
+                       }
+               }
+               (void) lseek(utmpf, (off_t)0, L_SET);
+               cc = read(utmpf, (char *)utmp, stb.st_size);
+               if (cc < 0) {
+                       fprintf(stderr, "rwhod: %s: %s\n",
+                           _PATH_UTMP, strerror(errno));
+                       goto done;
+               }
+               wlast = &mywd.wd_we[1024 / sizeof(struct whoent) - 1];
+               utmpent = cc / sizeof(struct utmp);
+               for (i = 0; i < utmpent; i++)
+                       if (utmp[i].ut_name[0]) {
+                               memcpy(we->we_utmp.out_line, utmp[i].ut_line,
+                                  sizeof(utmp[i].ut_line));
+                               memcpy(we->we_utmp.out_name, utmp[i].ut_name,
+                                  sizeof(utmp[i].ut_name));
+                               we->we_utmp.out_time = htonl(utmp[i].ut_time);
+                               if (we >= wlast)
+                                       break;
+                               we++;
+                       }
+               utmpent = we - mywd.wd_we;
+       }
+
+       /*
+        * The test on utmpent looks silly---after all, if no one is
+        * logged on, why worry about efficiency?---but is useful on
+        * (e.g.) compute servers.
+        */
+       if (utmpent && chdir(_PATH_DEV)) {
+               syslog(LOG_ERR, "chdir(%s): %m", _PATH_DEV);
+               exit(1);
+       }
+       we = mywd.wd_we;
+       for (i = 0; i < utmpent; i++) {
+               if (stat(we->we_utmp.out_line, &stb) >= 0)
+                       we->we_idle = htonl(now - stb.st_atime);
+               we++;
+       }
+       (void)getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0]));
+       for (i = 0; i < 3; i++)
+               mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100));
+       cc = (char *)we - (char *)&mywd;
+       mywd.wd_sendtime = htonl(time(0));
+       mywd.wd_vers = WHODVERSION;
+       mywd.wd_type = WHODTYPE_STATUS;
+       for (np = neighbors; np != NULL; np = np->n_next)
+               (void)sendto(s, (char *)&mywd, cc, 0,
+                               np->n_addr, np->n_addrlen);
+       if (utmpent && chdir(_PATH_RWHODIR)) {
+               syslog(LOG_ERR, "chdir(%s): %m", _PATH_RWHODIR);
+               exit(1);
+       }
+done:
+       (void) alarm(AL_INTERVAL);
+}
+
+void
+getboottime(signo)
+       int signo;
+{
+       int mib[2];
+       size_t size;
+       struct timeval tm;
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_BOOTTIME;
+       size = sizeof(tm);
+       if (sysctl(mib, 2, &tm, &size, NULL, 0) == -1) {
+               syslog(LOG_ERR, "cannot get boottime: %m");
+               exit(1);
+       }
+       mywd.wd_boottime = htonl(tm.tv_sec);
+}
+
+void
+quit(msg)
+       char *msg;
+{
+       syslog(LOG_ERR, msg);
+       exit(1);
+}
+
+#define ROUNDUP(a) \
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+void
+rt_xaddrs(cp, cplim, rtinfo)
+       register caddr_t cp, cplim;
+       register struct rt_addrinfo *rtinfo;
+{
+       register struct sockaddr *sa;
+       register int i;
+
+       memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
+       for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+               if ((rtinfo->rti_addrs & (1 << i)) == 0)
+                       continue;
+               rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+               ADVANCE(cp, sa);
+       }
+}
+
+/*
+ * Figure out device configuration and select
+ * networks which deserve status information.
+ */
+int
+configure(s)
+       int s;
+{
+       register struct neighbor *np;
+       register struct if_msghdr *ifm;
+       register struct ifa_msghdr *ifam;
+       struct sockaddr_dl *sdl;
+       size_t needed;
+       int mib[6], flags = 0, len;
+       char *buf, *lim, *next;
+       struct rt_addrinfo info;
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;
+       mib[3] = AF_INET;
+       mib[4] = NET_RT_IFLIST;
+       mib[5] = 0;
+       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+               quit("route-sysctl-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               quit("malloc");
+       if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+               quit("actual retrieval of interface table");
+       lim = buf + needed;
+
+       sdl = NULL;             /* XXX just to keep gcc -Wall happy */
+       for (next = buf; next < lim; next += ifm->ifm_msglen) {
+               ifm = (struct if_msghdr *)next;
+               if (ifm->ifm_type == RTM_IFINFO) {
+                       sdl = (struct sockaddr_dl *)(ifm + 1);
+                       flags = ifm->ifm_flags;
+                       continue;
+               }
+               if ((flags & IFF_UP) == 0 ||
+                   (flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0)
+                       continue;
+               if (ifm->ifm_type != RTM_NEWADDR)
+                       quit("out of sync parsing NET_RT_IFLIST");
+               ifam = (struct ifa_msghdr *)ifm;
+               info.rti_addrs = ifam->ifam_addrs;
+               rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
+                       &info);
+               /* gag, wish we could get rid of Internet dependencies */
+#define dstaddr        info.rti_info[RTAX_BRD]
+#define IPADDR_SA(x) ((struct sockaddr_in *)(x))->sin_addr.s_addr
+#define PORT_SA(x) ((struct sockaddr_in *)(x))->sin_port
+               if (dstaddr == 0 || dstaddr->sa_family != AF_INET)
+                       continue;
+               PORT_SA(dstaddr) = sp->s_port;
+               for (np = neighbors; np != NULL; np = np->n_next)
+                       if (memcmp(sdl->sdl_data, np->n_name,
+                                  sdl->sdl_nlen) == 0 &&
+                           IPADDR_SA(np->n_addr) == IPADDR_SA(dstaddr))
+                               break;
+               if (np != NULL)
+                       continue;
+               len = sizeof(*np) + dstaddr->sa_len + sdl->sdl_nlen + 1;
+               np = (struct neighbor *)malloc(len);
+               if (np == NULL)
+                       quit("malloc of neighbor structure");
+               memset(np, 0, len);
+               np->n_flags = flags;
+               np->n_addr = (struct sockaddr *)(np + 1);
+               np->n_addrlen = dstaddr->sa_len;
+               np->n_name = np->n_addrlen + (char *)np->n_addr;
+               np->n_next = neighbors;
+               neighbors = np;
+               memcpy((char *)np->n_addr, (char *)dstaddr, np->n_addrlen);
+               memcpy(np->n_name, sdl->sdl_data, sdl->sdl_nlen);
+       }
+       free(buf);
+       return (1);
+}
+
+#ifdef DEBUG
+void
+Sendto(s, buf, cc, flags, to, tolen)
+       int s;
+       char *buf;
+       int cc, flags;
+       char *to;
+       int tolen;
+{
+       register struct whod *w = (struct whod *)buf;
+       register struct whoent *we;
+       struct sockaddr_in *sin = (struct sockaddr_in *)to;
+
+       printf("sendto %x.%d\n", ntohl(sin->sin_addr), ntohs(sin->sin_port));
+       printf("hostname %s %s\n", w->wd_hostname,
+          interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), "  up"));
+       printf("load %4.2f, %4.2f, %4.2f\n",
+           ntohl(w->wd_loadav[0]) / 100.0, ntohl(w->wd_loadav[1]) / 100.0,
+           ntohl(w->wd_loadav[2]) / 100.0);
+       cc -= WHDRSIZE;
+       for (we = w->wd_we, cc /= sizeof(struct whoent); cc > 0; cc--, we++) {
+               time_t t = ntohl(we->we_utmp.out_time);
+               printf("%-8.8s %s:%s %.12s",
+                       we->we_utmp.out_name,
+                       w->wd_hostname, we->we_utmp.out_line,
+                       ctime(&t)+4);
+               we->we_idle = ntohl(we->we_idle) / 60;
+               if (we->we_idle) {
+                       if (we->we_idle >= 100*60)
+                               we->we_idle = 100*60 - 1;
+                       if (we->we_idle >= 60)
+                               printf(" %2d", we->we_idle / 60);
+                       else
+                               printf("   ");
+                       printf(":%02d", we->we_idle % 60);
+               }
+               printf("\n");
+       }
+}
+
+char *
+interval(time, updown)
+       int time;
+       char *updown;
+{
+       static char resbuf[32];
+       int days, hours, minutes;
+
+       if (time < 0 || time > 3*30*24*60*60) {
+               (void) sprintf(resbuf, "   %s ??:??", updown);
+               return (resbuf);
+       }
+       minutes = (time + 59) / 60;             /* round to minutes */
+       hours = minutes / 60; minutes %= 60;
+       days = hours / 24; hours %= 24;
+       if (days)
+               (void) sprintf(resbuf, "%s %2d+%02d:%02d",
+                   updown, days, hours, minutes);
+       else
+               (void) sprintf(resbuf, "%s    %2d:%02d",
+                   updown, hours, minutes);
+       return (resbuf);
+}
+#endif
diff --git a/slattach.tproj/Makefile b/slattach.tproj/Makefile
new file mode 100644 (file)
index 0000000..1f2fd2d
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = slattach
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = slattach.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist slattach.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/slattach.tproj/Makefile.dist b/slattach.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..0a1e759
--- /dev/null
@@ -0,0 +1,7 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  slattach
+MAN8=  slattach.0
+MLINKS=        slattach.8 slip.8
+
+.include <bsd.prog.mk>
diff --git a/slattach.tproj/Makefile.preamble b/slattach.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/slattach.tproj/PB.project b/slattach.tproj/PB.project
new file mode 100644 (file)
index 0000000..df7d482
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (slattach.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, slattach.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = slattach; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = slattach; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = slattach; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = slattach; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/slattach.tproj/slattach.8 b/slattach.tproj/slattach.8
new file mode 100644 (file)
index 0000000..217c481
--- /dev/null
@@ -0,0 +1,90 @@
+.\" Copyright (c) 1986, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)slattach.8 8.2 (Berkeley) 4/1/94
+.\"
+.Dd April 1, 1994
+.Dt SLATTACH 8
+.Os BSD 4.3
+.Sh NAME
+.Nm slattach
+.Nd attach serial lines as network interfaces
+.Sh SYNOPSIS
+.Nm Slattach
+.Ar ttyname Op Ar baudrate
+.Sh DESCRIPTION
+.Nm Slattach
+is used to assign a tty line to a network interface,
+and to define the network source and destination addresses.
+The following operands are supported by
+.Nm slattach :
+.Bl -tag -width Ar
+.It Ar ttyname
+Specifies the name of the tty device.
+.Ar Ttyname
+should be a string of the form
+.Ql ttyXX ,
+or
+.Ql /dev/ttyXX .
+.It Ar baudrate
+Specifies the speed of the connection. If not specified, the
+default of 9600 is used.
+.El
+.Pp
+Only the super-user may attach a network interface.
+.Pp
+To detach the interface, use
+.Dq Li ifconfig interface-name down
+after killing off the
+.Nm slattach
+process.
+.Ar Interface-name
+is the name that is shown by
+.Xr netstat 1
+.Sh EXAMPLES
+.Bd -literal -offset indent -compact
+slattach ttyh8
+slattach /dev/tty01 4800
+.Ed
+.Sh DIAGNOSTICS
+Messages indicating the specified interface does not exit, the
+requested address is unknown, the user is not privileged and
+tried to alter an interface's configuration.
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr netintro 4 ,
+.Xr ifconfig 8 ,
+.Xr rc 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/slattach.tproj/slattach.c b/slattach.tproj/slattach.c
new file mode 100644 (file)
index 0000000..580da18
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Adams.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sgtty.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <paths.h>
+
+#define DEFAULT_BAUD   9600
+int    slipdisc = SLIPDISC;
+
+__private_extern__
+char   devname[32] = { '\0' };
+char   hostname[MAXHOSTNAMELEN];
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register int fd;
+       register char *dev = argv[1];
+       struct sgttyb sgtty;
+       int     speed;
+
+       if (argc < 2 || argc > 3) {
+               fprintf(stderr, "usage: %s ttyname [baudrate]\n", argv[0]);
+               exit(1);
+       }
+       speed = argc == 3 ? findspeed(atoi(argv[2])) : findspeed(DEFAULT_BAUD);
+       if (speed == 0) {
+               fprintf(stderr, "unknown speed %s", argv[2]);
+               exit(1);
+       }
+       if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
+               (void)snprintf(devname, sizeof(devname),
+                   "%s%s", _PATH_DEV, dev);
+               dev = devname;
+       }
+       if ((fd = open(dev, O_RDWR | O_NDELAY)) < 0) {
+               perror(dev);
+               exit(1);
+       }
+       sgtty.sg_flags = RAW | ANYP;
+       sgtty.sg_ispeed = sgtty.sg_ospeed = speed;
+       if (ioctl(fd, TIOCSETP, &sgtty) < 0) {
+               perror("ioctl(TIOCSETP)");
+               exit(1);
+       }
+       if (ioctl(fd, TIOCSETD, &slipdisc) < 0) {
+               perror("ioctl(TIOCSETD)");
+               exit(1);
+       }
+
+       if (fork() > 0)
+               exit(0);
+       for (;;)
+               sigpause(0L);
+}
+
+struct sg_spds {
+       int sp_val, sp_name;
+}       spds[] = {
+#ifdef B50
+       { 50, B50 },
+#endif
+#ifdef B75
+       { 75, B75 },
+#endif
+#ifdef B110
+       { 110, B110 },
+#endif
+#ifdef B150
+       { 150, B150 },
+#endif
+#ifdef B200
+       { 200, B200 },
+#endif
+#ifdef B300
+       { 300, B300 },
+#endif
+#ifdef B600
+       { 600, B600 },
+#endif
+#ifdef B1200
+       { 1200, B1200 },
+#endif
+#ifdef B1800
+       { 1800, B1800 },
+#endif
+#ifdef B2000
+       { 2000, B2000 },
+#endif
+#ifdef B2400
+       { 2400, B2400 },
+#endif
+#ifdef B3600
+       { 3600, B3600 },
+#endif
+#ifdef B4800
+       { 4800, B4800 },
+#endif
+#ifdef B7200
+       { 7200, B7200 },
+#endif
+#ifdef B9600
+       { 9600, B9600 },
+#endif
+#ifdef EXTA
+       { 19200, EXTA },
+#endif
+#ifdef EXTB
+       { 38400, EXTB },
+#endif
+       { 0, 0 }
+};
+
+findspeed(speed)
+       register int speed;
+{
+       register struct sg_spds *sp;
+
+       sp = spds;
+       while (sp->sp_val && sp->sp_val != speed)
+               sp++;
+       return (sp->sp_name);
+}
diff --git a/sliplogin.tproj/Makefile b/sliplogin.tproj/Makefile
new file mode 100644 (file)
index 0000000..b106e74
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = sliplogin
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = sliplogin.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sliplogin.8\
+            slip.hosts slip.login
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/sliplogin.tproj/Makefile.postamble b/sliplogin.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..de54c24
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+INSTALL_PERMISSIONS = 4555        # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
diff --git a/sliplogin.tproj/Makefile.preamble b/sliplogin.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2c9003c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/sliplogin.tproj/PB.project b/sliplogin.tproj/PB.project
new file mode 100644 (file)
index 0000000..04d7107
--- /dev/null
@@ -0,0 +1,48 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pathnames.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (sliplogin.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            sliplogin.8, 
+            slip.hosts, 
+            slip.login
+        ); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = sliplogin; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/sliplogin.tproj/pathnames.h b/sliplogin.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..3060035
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#ifndef COMPAT
+#include <paths.h>
+#else
+#define        _PATH_DEVNULL   "/dev/null"
+#endif
+
+#define        _PATH_ACCESS    "/etc/sliphome/slip.hosts"
+#define        _PATH_LOGIN     "/etc/sliphome/slip.login"
+#define        _PATH_LOGOUT    "/etc/sliphome/slip.logout"
+#define        _PATH_DEBUG     "/tmp/sliplogin.XXXXXX"
+
diff --git a/sliplogin.tproj/slip.hosts b/sliplogin.tproj/slip.hosts
new file mode 100644 (file)
index 0000000..f6ebf40
--- /dev/null
@@ -0,0 +1,11 @@
+#      @(#)slip.hosts  8.1 (Berkeley) 6/6/93
+#
+# login                local-addr      remote-addr     mask            opt1    opt2
+#                                              (normal,compress,noicmp)
+#
+Schez          vangogh         chez            0xffffff00      compress
+Sjun           vangogh         128.32.130.36   0xffffff00      normal
+Sleconte       vangogh         leconte         0xffffff00      compress
+Sleeb          vangogh         leeb            0xffffff00      compress
+Smjk           vangogh         pissaro-sl      0xffffff00      compress
+Soxford                vangogh         oxford          0xffffff00      compress
diff --git a/sliplogin.tproj/slip.login b/sliplogin.tproj/slip.login
new file mode 100644 (file)
index 0000000..3c70095
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh -
+#
+#      @(#)slip.login  8.1 (Berkeley) 6/6/93
+
+#
+# generic login file for a slip line.  sliplogin invokes this with
+# the parameters:
+#      1        2         3        4          5         6     7-n
+#   slipunit ttyspeed loginname local-addr remote-addr mask opt-args
+#
+/sbin/ifconfig sl$1 inet $4 $5 netmask $6 
+exit
diff --git a/sliplogin.tproj/sliplogin.8 b/sliplogin.tproj/sliplogin.8
new file mode 100644 (file)
index 0000000..1c71988
--- /dev/null
@@ -0,0 +1,220 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)sliplogin.8        8.2 (Berkeley) 1/5/94
+.\"
+.Dd January 5, 1994
+.Dt SLIPLOGIN 8
+.Os
+.Sh NAME
+.Nm sliplogin
+.Nd attach a serial line network interface
+.Sh SYNOPSIS
+.Nm sliplogin
+.Op Ar loginname
+.Sh DESCRIPTION
+.Nm Sliplogin
+is used to turn the terminal line on standard input into
+a Serial Line IP
+.Pq Tn SLIP
+link to a remote host.  To do this, the program
+searches the file
+.Pa /etc/sliphome/slip.hosts
+for an entry matching
+.Ar loginname
+(which defaults to the current login name if omitted).
+If a matching entry is found, the line is configured appropriately
+for slip (8-bit transparent i/o) and converted to
+.Tn SLIP
+line
+discipline.  Then a shell script is invoked to initialize the slip
+interface with the appropriate local and remote
+.Tn IP
+address,
+netmask, etc.
+.Pp
+The usual initialization script is
+.Pa /etc/sliphome/slip.login
+but, if particular hosts need special initialization, the file
+.Pa /etc/sliphome/slip.login. Ns Ar loginname
+will be executed instead if it exists.
+The script is invoked with the parameters
+.Bl -tag -width slipunit
+.It Em slipunit
+The unit number of the slip interface assigned to this line.  E.g.,
+.Sy 0
+for
+.Sy sl0 .
+.It Em speed
+The speed of the line.
+.It Em args
+The arguments from the
+.Pa /etc/sliphome/slip.hosts
+entry, in order starting with
+.Ar loginname .
+.El
+.Pp
+Only the super-user may attach a network interface.  The interface is
+automatically detached when the other end hangs up or the
+.Nm sliplogin
+process dies.  If the kernel slip
+module has been configured for it, all routes through that interface will
+also disappear at the same time.  If there is other processing a site
+would like done on hangup, the file
+.Pa /etc/sliphome/slip.logout
+or
+.Pa /etc/sliphome/slip.logout. Ns Ar loginname
+is executed if it exists.  It is given the same arguments as the login script.
+.Ss Format of /etc/sliphome/slip.hosts
+Comments (lines starting with a `#') and blank lines are ignored.
+Other lines must start with a
+.Ar loginname
+but the remaining arguments can be whatever is appropriate for the
+.Pa  slip.login
+file that will be executed for that name.
+Arguments are separated by white space and follow normal
+.Xr sh 1
+quoting conventions (however,
+.Ar loginname
+cannot be quoted).
+Usually, lines have the form
+.Bd -literal -offset indent
+loginname local-address remote-address netmask opt-args
+.Ed
+.Pp
+where
+.Em local-address
+and
+.Em remote-address
+are the IP host names or addresses of the local and remote ends of the
+slip line and
+.Em netmask
+is the appropriate IP netmask.  These arguments are passed
+directly to
+.Xr ifconfig 8 .
+.Em Opt-args
+are optional arguments used to configure the line.
+.Sh EXAMPLE
+The normal use of
+.Nm sliplogin
+is to create a
+.Pa /etc/passwd
+entry for each legal, remote slip site with
+.Nm sliplogin
+as the shell for that entry.  E.g.,
+.Bd -literal
+Sfoo:ikhuy6:2010:1:slip line to foo:/tmp:/usr/sbin/sliplogin
+.Ed
+.Pp
+(Our convention is to name the account used by remote host
+.Ar hostname
+as
+.Em Shostname . )
+Then an entry is added to
+.Pa slip.hosts
+that looks like:
+.Pp
+.Bd -literal -offset indent -compact
+Sfoo   `hostname`      foo     netmask
+.Ed
+.Pp
+where
+.Em `hostname`
+will be evaluated by
+.Xr sh
+to the local host name and
+.Em netmask
+is the local host IP netmask.
+.Pp
+Note that
+.Nm sliplogin
+must be setuid to root and, while not a security hole, moral defectives
+can use it to place terminal lines in an unusable state and/or deny
+access to legitimate users of a remote slip line.  To prevent this,
+a site can create a group, say
+.Em slip ,
+that only the slip login accounts are put in then make sure that
+.Pa /usr/sbin/sliplogin
+is in group
+.Em slip
+and mode 4550 (setuid root, only group
+.Em slip
+can execute binary).
+.Sh DIAGNOSTICS
+.Nm Sliplogin
+logs various information to the system log daemon,
+.Xr syslogd 8 ,
+with a facility code of
+.Em daemon .
+The messages are listed here, grouped by severity level.
+.Pp
+.Sy Error Severity
+.Bl -tag -width Ds -compact
+.It Sy ioctl (TCGETS): Em reason
+A
+.Dv TCGETS
+.Fn ioctl
+to get the line parameters failed.
+.Pp
+.It Sy ioctl (TCSETS): Em reason
+A
+.Dv TCSETS
+.Fn ioctl
+to set the line parameters failed.
+.Pp
+.It Sy /etc/sliphome/slip.hosts: Em reason
+The
+.Pa /etc/sliphome/slip.hosts
+file could not be opened.
+.Pp
+.It Sy access denied for Em user
+No entry for
+.Em user
+was found in
+.Pa /etc/sliphome/slip.hosts .
+.El
+.Pp
+.Sy Notice Severity
+.Bl -tag -width Ds -compact
+.It Sy "attaching slip unit" Em unit Sy for Ar loginname
+.Tn SLIP
+unit
+.Em unit
+was successfully attached.
+.El
+.Sh SEE ALSO
+.Xr slattach 8 ,
+.Xr syslogd 8
+.Sh HISTORY
+The
+.Nm
+command
+.Bt
diff --git a/sliplogin.tproj/sliplogin.c b/sliplogin.tproj/sliplogin.c
new file mode 100644 (file)
index 0000000..d1cdcab
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)sliplogin.c        8.2 (Berkeley) 2/1/94";
+#endif /* not lint */
+
+/*
+ * sliplogin.c
+ * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!]
+ *
+ * This program initializes its own tty port to be an async TCP/IP interface.
+ * It sets the line discipline to slip, invokes a shell script to initialize
+ * the network interface, then pauses forever waiting for hangup.
+ *
+ * It is a remote descendant of several similar programs with incestuous ties:
+ * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL.
+ * - slattach, probably by Rick Adams but touched by countless hordes.
+ * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it.
+ *
+ * There are two forms of usage:
+ *
+ * "sliplogin"
+ * Invoked simply as "sliplogin", the program looks up the username
+ * in the file /etc/slip.hosts.
+ * If an entry is found, the line on fd0 is configured for SLIP operation
+ * as specified in the file.
+ *
+ * "sliplogin IPhostlogin </dev/ttyb"
+ * Invoked by root with a username, the name is looked up in the
+ * /etc/slip.hosts file and if found fd0 is configured as in case 1.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <sys/file.h>
+#include <sys/syslog.h>
+#include <netdb.h>
+
+#if BSD >= 199006
+#define POSIX
+#endif
+#ifdef POSIX
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+#include <ttyent.h>
+#else
+#include <sgtty.h>
+#endif
+#include <net/slip.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include "pathnames.h"
+
+int    unit;
+int    speed;
+int    uid;
+char   loginargs[BUFSIZ];
+char   loginfile[MAXPATHLEN];
+char   loginname[BUFSIZ];
+
+void
+findid(name)
+       char *name;
+{
+       FILE *fp;
+       static char slopt[5][16];
+       static char laddr[16];
+       static char raddr[16];
+       static char mask[16];
+       char user[16];
+       int i, j, n;
+
+       (void)strcpy(loginname, name);
+       if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) {
+               (void)fprintf(stderr, "sliplogin: %s: %s\n",
+                   _PATH_ACCESS, strerror(errno));
+               syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS);
+               exit(1);
+       }
+       while (fgets(loginargs, sizeof(loginargs) - 1, fp)) {
+               if (ferror(fp))
+                       break;
+               n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n",
+                        user, laddr, raddr, mask, slopt[0], slopt[1], 
+                       slopt[2], slopt[3], slopt[4]);
+               if (user[0] == '#' || isspace(user[0]))
+                       continue;
+               if (strcmp(user, name) != 0)
+                       continue;
+
+               /*
+                * we've found the guy we're looking for -- see if
+                * there's a login file we can use.  First check for
+                * one specific to this host.  If none found, try for
+                * a generic one.
+                */
+               (void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name);
+               if (access(loginfile, R_OK|X_OK) != 0) {
+                       (void)strcpy(loginfile, _PATH_LOGIN);
+                       if (access(loginfile, R_OK|X_OK)) {
+                               fputs("access denied - no login file\n",
+                                     stderr);
+                               syslog(LOG_ERR,
+                                      "access denied for %s - no %s\n",
+                                      name, _PATH_LOGIN);
+                               exit(5);
+                       }
+               }
+
+               (void) fclose(fp);
+               return;
+       }
+       (void)fprintf(stderr, "SLIP access denied for %s\n", name);
+       syslog(LOG_ERR, "SLIP access denied for %s\n", name);
+       exit(4);
+       /* NOTREACHED */
+}
+
+char *
+sigstr(s)
+       int s;
+{
+       static char buf[32];
+
+       switch (s) {
+       case SIGHUP:    return("HUP");
+       case SIGINT:    return("INT");
+       case SIGQUIT:   return("QUIT");
+       case SIGILL:    return("ILL");
+       case SIGTRAP:   return("TRAP");
+       case SIGIOT:    return("IOT");
+       case SIGEMT:    return("EMT");
+       case SIGFPE:    return("FPE");
+       case SIGKILL:   return("KILL");
+       case SIGBUS:    return("BUS");
+       case SIGSEGV:   return("SEGV");
+       case SIGSYS:    return("SYS");
+       case SIGPIPE:   return("PIPE");
+       case SIGALRM:   return("ALRM");
+       case SIGTERM:   return("TERM");
+       case SIGURG:    return("URG");
+       case SIGSTOP:   return("STOP");
+       case SIGTSTP:   return("TSTP");
+       case SIGCONT:   return("CONT");
+       case SIGCHLD:   return("CHLD");
+       case SIGTTIN:   return("TTIN");
+       case SIGTTOU:   return("TTOU");
+       case SIGIO:     return("IO");
+       case SIGXCPU:   return("XCPU");
+       case SIGXFSZ:   return("XFSZ");
+       case SIGVTALRM: return("VTALRM");
+       case SIGPROF:   return("PROF");
+       case SIGWINCH:  return("WINCH");
+#ifdef SIGLOST
+       case SIGLOST:   return("LOST");
+#endif
+       case SIGUSR1:   return("USR1");
+       case SIGUSR2:   return("USR2");
+       }
+       (void)sprintf(buf, "sig %d", s);
+       return(buf);
+}
+
+void
+hup_handler(s)
+       int s;
+{
+       char logoutfile[MAXPATHLEN];
+
+       (void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, loginname);
+       if (access(logoutfile, R_OK|X_OK) != 0)
+               (void)strcpy(logoutfile, _PATH_LOGOUT);
+       if (access(logoutfile, R_OK|X_OK) == 0) {
+               char logincmd[2*MAXPATHLEN+32];
+
+               (void) sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed,
+                             loginargs);
+               (void) system(logincmd);
+       }
+       (void) close(0);
+       syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit,
+              sigstr(s));
+       exit(1);
+       /* NOTREACHED */
+}
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int fd, s, ldisc, odisc;
+       char *name;
+#ifdef POSIX
+       struct termios tios, otios;
+#else
+       struct sgttyb tty, otty;
+#endif
+       char logincmd[2*BUFSIZ+32];
+       extern uid_t getuid();
+
+       if ((name = strrchr(argv[0], '/')) == NULL)
+               name = argv[0];
+       s = getdtablesize();
+       for (fd = 3 ; fd < s ; fd++)
+               (void) close(fd);
+       openlog(name, LOG_PID, LOG_DAEMON);
+       uid = getuid();
+       if (argc > 1) {
+               findid(argv[1]);
+
+               /*
+                * Disassociate from current controlling terminal, if any,
+                * and ensure that the slip line is our controlling terminal.
+                */
+#ifdef POSIX
+               if (fork() > 0)
+                       exit(0);
+               if (setsid() != 0)
+                       perror("setsid");
+#else
+               if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) {
+                       extern char *ttyname();
+
+                       (void) ioctl(fd, TIOCNOTTY, (caddr_t)0);
+                       (void) close(fd);
+                       /* open slip tty again to acquire as controlling tty? */
+                       fd = open(ttyname(0), O_RDWR, 0);
+                       if (fd >= 0)
+                               (void) close(fd);
+               }
+               (void) setpgrp(0, getpid());
+#endif
+               if (argc > 2) {
+                       if ((fd = open(argv[2], O_RDWR)) == -1) {
+                               perror(argv[2]);
+                               exit(2);
+                       }
+                       (void) dup2(fd, 0);
+                       if (fd > 2)
+                               close(fd);
+               }
+#ifdef TIOCSCTTY
+               if (ioctl(0, TIOCSCTTY, (caddr_t)0) != 0)
+                       perror("ioctl (TIOCSCTTY)");
+#endif
+       } else {
+               extern char *getlogin();
+
+               if ((name = getlogin()) == NULL) {
+                       (void) fprintf(stderr, "access denied - no username\n");
+                       syslog(LOG_ERR, "access denied - getlogin returned 0\n");
+                       exit(1);
+               }
+               findid(name);
+       }
+       (void) fchmod(0, 0600);
+       (void) fprintf(stderr, "starting slip login for %s\n", loginname);
+#ifdef POSIX
+       /* set up the line parameters */
+       if (tcgetattr(0, &tios) < 0) {
+               syslog(LOG_ERR, "tcgetattr: %m");
+               exit(1);
+       }
+       otios = tios;
+       cfmakeraw(&tios);
+       tios.c_iflag &= ~IMAXBEL;
+       if (tcsetattr(0, TCSAFLUSH, &tios) < 0) {
+               syslog(LOG_ERR, "tcsetattr: %m");
+               exit(1);
+       }
+       speed = cfgetispeed(&tios);
+#else
+       /* set up the line parameters */
+       if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) {
+               syslog(LOG_ERR, "ioctl (TIOCGETP): %m");
+               exit(1);
+       }
+       otty = tty;
+       speed = tty.sg_ispeed;
+       tty.sg_flags = RAW | ANYP;
+       if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) {
+               syslog(LOG_ERR, "ioctl (TIOCSETP): %m");
+               exit(1);
+       }
+#endif
+       /* find out what ldisc we started with */
+       if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) {
+               syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m");
+               exit(1);
+       }
+       ldisc = SLIPDISC;
+       if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) {
+               syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
+               exit(1);
+       }
+       /* find out what unit number we were assigned */
+       if (ioctl(0, SLIOCGUNIT, (caddr_t)&unit) < 0) {
+               syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m");
+               exit(1);
+       }
+       (void) signal(SIGHUP, hup_handler);
+       (void) signal(SIGTERM, hup_handler);
+
+       syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname);
+       (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed,
+                     loginargs);
+       /*
+        * aim stdout and errout at /dev/null so logincmd output won't
+        * babble into the slip tty line.
+        */
+       (void) close(1);
+       if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != 1) {
+               if (fd < 0) {
+                       syslog(LOG_ERR, "open /dev/null: %m");
+                       exit(1);
+               }
+               (void) dup2(fd, 1);
+               (void) close(fd);
+       }
+       (void) dup2(1, 2);
+
+       /*
+        * Run login and logout scripts as root (real and effective);
+        * current route(8) is setuid root, and checks the real uid
+        * to see whether changes are allowed (or just "route get").
+        */
+       (void) setuid(0);
+       if (s = system(logincmd)) {
+               syslog(LOG_ERR, "%s login failed: exit status %d from %s",
+                      loginname, s, loginfile);
+               (void) ioctl(0, TIOCSETD, (caddr_t)&odisc);
+               exit(6);
+       }
+
+       /* twiddle thumbs until we get a signal */
+       while (1)
+               sigpause(0);
+
+       /* NOTREACHED */
+}
diff --git a/spray.tproj/Makefile b/spray.tproj/Makefile
new file mode 100644 (file)
index 0000000..ad3c8d3
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = spray
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = spray.c
+
+OTHERSRCS = Makefile Makefile.dist Makefile.postamble Makefile.preamble\
+            spray.x
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/spray.tproj/Makefile.dist b/spray.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..87c00aa
--- /dev/null
@@ -0,0 +1,7 @@
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:58:27 wsanchez Exp $
+
+PROG=  spray
+NOMAN=
+LDADD= -lrpcsvc
+
+.include <bsd.prog.mk>
diff --git a/spray.tproj/Makefile.postamble b/spray.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..6e5046f
--- /dev/null
@@ -0,0 +1,126 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+
+%_xdr.c: %.x
+       $(RPCGEN) $(ALL_RPCFLAGS) -c -o $(SYM_DIR)/$*_xdr.c $*.x
+
diff --git a/spray.tproj/Makefile.preamble b/spray.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..31db359
--- /dev/null
@@ -0,0 +1,4 @@
+OTHER_OFILES = spray_xdr.o 
+OTHER_INITIAL_TARGETS = spray.h
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/spray.tproj/PB.project b/spray.tproj/PB.project
new file mode 100644 (file)
index 0000000..72b61e4
--- /dev/null
@@ -0,0 +1,37 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (spray.c); 
+        OTHER_SOURCES = (Makefile, Makefile.dist, Makefile.postamble, Makefile.preamble, spray.x); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = spray; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/spray.tproj/spray.c b/spray.tproj/spray.c
new file mode 100644 (file)
index 0000000..72d9c3e
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     $Id: spray.c,v 1.1.1.1 1999/05/02 03:58:27 wsanchez Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpcsvc/spray.h>
+
+#ifndef SPRAYOVERHEAD
+#define SPRAYOVERHEAD  86
+#endif
+
+void usage ();
+void print_xferstats ();
+
+/* spray buffer */
+char spray_buffer[SPRAYMAX];
+
+/* RPC timeouts */
+struct timeval NO_DEFAULT = { -1, -1 };
+struct timeval ONE_WAY = { 0, 0 };
+struct timeval TIMEOUT = { 25, 0 };
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       char *progname;
+       spraycumul      host_stats;
+       sprayarr        host_array;
+       CLIENT *cl;
+       int c;
+       int i;
+       int count = 0;
+       int delay = 0;
+       int length = 0;
+       double xmit_time;                       /* time to receive data */
+
+       progname = *argv;
+       while ((c = getopt(argc, argv, "c:d:l:")) != -1) {
+               switch (c) {
+               case 'c':
+                       count = atoi(optarg);
+                       break;
+               case 'd':
+                       delay = atoi(optarg);
+                       break;
+               case 'l':
+                       length = atoi(optarg);
+                       break;
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 1) {
+               usage();
+               /* NOTREACHED */
+       }
+
+
+       /* Correct packet length. */
+       if (length > SPRAYMAX) {
+               length = SPRAYMAX;
+       } else if (length < SPRAYOVERHEAD) {
+               length = SPRAYOVERHEAD;
+       } else {
+               /* The RPC portion of the packet is a multiple of 32 bits. */
+               length -= SPRAYOVERHEAD - 3;
+               length &= ~3;
+               length += SPRAYOVERHEAD;
+       }
+
+
+       /*
+        * The default value of count is the number of packets required
+        * to make the total stream size 100000 bytes.
+        */
+       if (!count) {
+               count = 100000 / length;
+       }
+
+       /* Initialize spray argument */
+       host_array.sprayarr_len = length - SPRAYOVERHEAD;
+       host_array.sprayarr_val = spray_buffer;
+       
+
+       /* create connection with server */
+       cl = clnt_create(*argv, SPRAYPROG, SPRAYVERS, "udp");
+       if (cl == NULL) {
+               clnt_pcreateerror(progname);
+               exit(1);
+       }
+
+
+       /*
+        * For some strange reason, RPC 4.0 sets the default timeout, 
+        * thus timeouts specified in clnt_call() are always ignored.  
+        *
+        * The following (undocumented) hack resets the internal state
+        * of the client handle.
+        */
+       clnt_control(cl, CLSET_TIMEOUT, &NO_DEFAULT);
+
+
+       /* Clear server statistics */
+       if (clnt_call(cl, SPRAYPROC_CLEAR, xdr_void, NULL, xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
+               clnt_perror(cl, progname);
+               exit(1);
+       }
+
+
+       /* Spray server with packets */
+       printf ("sending %d packets of lnth %d to %s ...", count, length, *argv);
+       fflush (stdout);
+
+       for (i = 0; i < count; i++) {
+               clnt_call(cl, SPRAYPROC_SPRAY, xdr_sprayarr, &host_array, xdr_void, NULL, ONE_WAY);
+
+               if (delay) {
+                       usleep(delay);
+               }
+       }
+
+
+       /* Collect statistics from server */
+       if (clnt_call(cl, SPRAYPROC_GET, xdr_void, NULL, xdr_spraycumul, &host_stats, TIMEOUT) != RPC_SUCCESS) {
+               clnt_perror(cl, progname);
+               exit(1);
+       }
+
+       xmit_time = host_stats.clock.sec +
+                       (host_stats.clock.usec / 1000000.0);
+
+       printf ("\n\tin %.2f seconds elapsed time\n", xmit_time);
+
+
+       /* report dropped packets */
+       if (host_stats.counter != count) {
+               int packets_dropped = count - host_stats.counter;
+
+               printf("\t%d packets (%.2f%%) dropped\n",
+                       packets_dropped,
+                       100.0 * packets_dropped / count );
+       } else {
+               printf("\tno packets dropped\n");
+       }
+
+       printf("Sent:");
+       print_xferstats(count, length, xmit_time);
+
+       printf("Rcvd:");
+       print_xferstats(host_stats.counter, length, xmit_time);
+       
+       exit (0);
+}
+
+
+void
+print_xferstats(packets, packetlen, xfertime)
+       int packets;
+       int packetlen;
+       double xfertime;
+{
+       int datalen;
+       double pps;             /* packets per second */
+       double bps;             /* bytes per second */
+
+       datalen = packets * packetlen;
+       pps = packets / xfertime;
+       bps = datalen / xfertime;
+
+       printf("\t%.0f packets/sec, ", pps);
+
+       if (bps >= 1024) 
+               printf ("%.1fK ", bps / 1024);
+       else
+               printf ("%.0f ", bps);
+       
+       printf("bytes/sec\n");
+}
+
+
+void
+usage ()
+{
+       fprintf(stderr, "usage: spray [-c count] [-l length] [-d delay] host\n");
+       exit(1);
+}
diff --git a/spray.tproj/spray.x b/spray.tproj/spray.x
new file mode 100644 (file)
index 0000000..5d2f883
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <rpcsvc/spray.x>
diff --git a/startslip.tproj/Makefile b/startslip.tproj/Makefile
new file mode 100644 (file)
index 0000000..968b995
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = startslip
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = startslip.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist startslip.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/startslip.tproj/Makefile.dist b/startslip.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..14c72bc
--- /dev/null
@@ -0,0 +1,6 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  startslip
+MAN8=  startslip.0
+
+.include <bsd.prog.mk>
diff --git a/startslip.tproj/Makefile.preamble b/startslip.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/startslip.tproj/PB.project b/startslip.tproj/PB.project
new file mode 100644 (file)
index 0000000..1ba4a2b
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (startslip.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, startslip.1); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = startslip; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = startslip; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = startslip; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = startslip; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/startslip.tproj/startslip.1 b/startslip.tproj/startslip.1
new file mode 100644 (file)
index 0000000..f12feab
--- /dev/null
@@ -0,0 +1,105 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)startslip.1        8.1 (Berkeley) 6/5/93
+.\"
+.Dd June 5, 1993
+.Dt STARTSLIP 1
+.Os BSD 4.4
+.Sh NAME
+.Nm startslip
+.Nd dial up and login to a slip server
+.Sh SYNOPSIS
+.Nm startslip
+.Op Fl d
+.Op Fl s Ar string
+.Op Fl A Ar annexname
+.Op Fl F Ar flowcontrol
+.Ar device user passwd
+.Sh DESCRIPTION
+.Nm Startslip
+opens the specified
+.Ar device .
+.Pp
+Once carrier is asserted
+.Nm startslip
+attempts to login as the specified
+.Ar user
+with the given
+.Ar password .
+If successful, it puts the device into the slip line discipline.
+If carrier drops and a
+.Dv SIGHUP
+is sent to
+.Nm startslip ,
+it closes the device and attempts to repeat the dialup and login sequence.
+.Pp
+Available options:
+.Bl -tag -width Ar
+.It Fl d
+.Nm Startslip
+prints out debugging information about what it is trying to do.
+.It Fl s Ar string
+The optional
+.Ar string
+is written to
+.Ar device .
+For a dialup modem,
+the string is used to specify a dial sequence.
+.It Fl A Ar annexname
+.Nm Startslip
+assumes it is connecting to a Xylogics Annex box and engages in an
+appropriate dialog using the
+.Ar user
+and
+.Ar passwd
+arguments.
+The
+.Ar annexname
+argument is a string that is used to match against the Annex prompt
+to determine when a connection has been established.
+.It Fl F Ar flowcontrol
+Determines the type of flow control used on
+.Ar device .
+Choices for
+.Ar flowcontrol
+are
+``none'' for no flow control (the default),
+``hw'' for hardware RTS/CTS flow control and
+``sw'' for software XON/XOFF flow control.
+.El
+.Sh SEE ALSO
+.Xr sliplogin 8
+.Sh HISTORY
+The
+.Nm startslip
+appeared in
+.Bx 4.4 .
diff --git a/startslip.tproj/startslip.c b/startslip.tproj/startslip.c
new file mode 100644 (file)
index 0000000..f424137
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#if BSD >= 199006
+#define POSIX
+#endif
+#ifdef POSIX
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+#else
+#include <sgtty.h>
+#endif
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/if_slvar.h>
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <signal.h>
+
+#define DEFAULT_BAUD    B9600
+int     speed = DEFAULT_BAUD;
+#define        FC_NONE         0       /* flow control: none */
+#define        FC_SW           1       /* flow control: software (XON/XOFF) */
+#define        FC_HW           2       /* flow control: hardware (RTS/CTS) */
+int    flowcontrol = FC_NONE;
+char   *annex;
+int    hup;
+int    logged_in;
+int    wait_time = 60;         /* then back off */
+#define        MAXTRIES        6       /* w/60 sec and doubling, takes an hour */
+#define        PIDFILE         "/var/run/startslip.pid"
+
+#ifdef DEBUG
+int    debug = 1;
+#undef LOG_ERR
+#undef LOG_INFO
+#define syslog fprintf
+#define LOG_ERR stderr
+#define LOG_INFO stderr
+#else
+int    debug = 0;
+#endif
+#define        printd  if (debug) printf
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern char *optarg;
+       extern int optind;
+       char *cp, **ap;
+       int ch, disc;
+       int fd = -1;
+       void sighup();
+       FILE *wfd = NULL, *pfd;
+       char *dialerstring = 0, buf[BUFSIZ];
+       int first = 1, tries = 0;
+       int pausefirst = 0;
+       int pid;
+#ifdef POSIX
+       struct termios t;
+#else
+       struct sgttyb sgtty;
+#endif
+
+       while ((ch = getopt(argc, argv, "db:s:p:A:F:")) != EOF)
+               switch (ch) {
+               case 'd':
+                       debug = 1;
+                       break;
+#ifdef POSIX
+               case 'b':
+                       speed = atoi(optarg);
+                       break;
+#endif
+               case 'p':
+                       pausefirst = atoi(optarg);
+                       break;
+               case 's':
+                       dialerstring = optarg;
+                       break;
+               case 'A':
+                       annex = optarg;
+                       break;
+               case 'F':
+#ifdef POSIX
+                       if (strcmp(optarg, "none") == 0)
+                               flowcontrol = FC_NONE;
+                       else if (strcmp(optarg, "sw") == 0)
+                               flowcontrol = FC_SW;
+                       else if (strcmp(optarg, "hw") == 0)
+                               flowcontrol = FC_HW;
+                       else {
+                               (void)fprintf(stderr,
+                                       "flow control: none, sw, hw\n");
+                               exit(1);
+                       }
+                       break;
+#else
+                       (void)fprintf(stderr, "flow control not supported\n");
+                       exit(1);
+#endif
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 3)
+               usage();
+
+       openlog("startslip", LOG_PID, LOG_DAEMON);
+
+#if BSD <= 43
+       if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) {
+               ioctl(fd, TIOCNOTTY, 0);
+               close(fd);
+               fd = -1;
+       }
+#endif
+
+       if (debug)
+               setbuf(stdout, NULL);
+       
+       if (pfd = fopen(PIDFILE, "r")) {
+               pid = 0;
+               fscanf(pfd, "%d", &pid);
+               if (pid > 0)
+                       kill(pid, SIGUSR1);
+               fclose(pfd);
+       }
+restart:
+       logged_in = 0;
+       if (++tries > MAXTRIES) {
+               syslog(LOG_ERR, "exiting after %d tries\n", tries);
+               /* ???
+               if (first)
+               */
+                       exit(1);
+       }
+
+       /*
+        * We may get a HUP below, when the parent (session leader/
+        * controlling process) exits; ignore HUP until into new session.
+        */
+       signal(SIGHUP, SIG_IGN);
+       hup = 0;
+       if (fork() > 0) {
+               if (pausefirst)
+                       sleep(pausefirst);
+               if (first)
+                       printd("parent exit\n");
+               exit(0);
+       }
+       pausefirst = 0;
+#ifdef POSIX
+       if (setsid() == -1)
+               perror("setsid");
+#endif
+       pid = getpid();
+       printd("restart: pid %d: ", pid);
+       if (pfd = fopen(PIDFILE, "w")) {
+               fprintf(pfd, "%d\n", pid);
+               fclose(pfd);
+       }
+       if (wfd) {
+               printd("fclose, ");
+               fclose(wfd);
+               wfd == NULL;
+       }
+       if (fd >= 0) {
+               printd("close, ");
+               close(fd);
+               sleep(5);
+       }
+       printd("open");
+       if ((fd = open(argv[0], O_RDWR)) < 0) {
+               perror(argv[0]);
+               syslog(LOG_ERR, "open %s: %m\n", argv[0]);
+               if (first)
+                       exit(1);
+               else {
+                       sleep(wait_time * tries);
+                       goto restart;
+               }
+       }
+       printd(" %d", fd);
+#ifdef TIOCSCTTY
+       if (ioctl(fd, TIOCSCTTY, 0) < 0)
+               perror("ioctl (TIOCSCTTY)");
+#endif
+       signal(SIGHUP, sighup);
+       if (debug) {
+               if (ioctl(fd, TIOCGETD, &disc) < 0)
+                       perror("ioctl(TIOCSETD)");
+               printf(" (disc was %d)", disc);
+       }
+       disc = TTYDISC;
+       if (ioctl(fd, TIOCSETD, &disc) < 0) {
+               perror("ioctl(TIOCSETD)");
+               syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n",
+                   argv[0]);
+       }
+       printd(", ioctl");
+#ifdef POSIX
+       if (tcgetattr(fd, &t) < 0) {
+               perror("tcgetattr");
+               syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]);
+               exit(2);
+       }
+       cfmakeraw(&t);
+       t.c_iflag &= ~IMAXBEL;
+       switch (flowcontrol) {
+       case FC_HW:
+               t.c_cflag |= (CRTS_IFLOW|CCTS_OFLOW);
+               break;
+       case FC_SW:
+               t.c_iflag |= (IXON|IXOFF);
+               break;
+       case FC_NONE:
+               t.c_cflag &= ~(CRTS_IFLOW|CCTS_OFLOW);
+               t.c_iflag &= ~(IXON|IXOFF);
+               break;
+       }
+       cfsetspeed(&t, speed);
+       if (tcsetattr(fd, TCSAFLUSH, &t) < 0) {
+               perror("tcsetattr");
+               syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]);
+               if (first) 
+                       exit(2);
+               else {
+                       sleep(wait_time * tries);
+                       goto restart;
+               }
+       }
+#else
+       if (ioctl(fd, TIOCGETP, &sgtty) < 0) {
+               perror("ioctl (TIOCGETP)");
+               syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n",
+                   argv[0]);
+               exit(2);
+       }
+       sgtty.sg_flags = RAW | ANYP;
+       sgtty.sg_erase = sgtty.sg_kill = 0377;
+       sgtty.sg_ispeed = sgtty.sg_ospeed = speed;
+       if (ioctl(fd, TIOCSETP, &sgtty) < 0) {
+               perror("ioctl (TIOCSETP)");
+               syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n",
+                   argv[0]);
+               if (first) 
+                       exit(2);
+               else {
+                       sleep(wait_time * tries);
+                       goto restart;
+               }
+       }
+#endif
+       sleep(2);               /* wait for flakey line to settle */
+       if (hup)
+               goto restart;
+
+       wfd = fdopen(fd, "w+");
+       if (wfd == NULL) {
+               syslog(LOG_ERR, "can't fdopen slip line\n");
+               exit(10);
+       }
+       setbuf(wfd, (char *)0);
+       if (dialerstring) {
+               printd(", send dialstring");
+               fprintf(wfd, "%s\r", dialerstring);
+       } else
+               putc('\r', wfd);
+       printd("\n");
+
+       /*
+        * Log in
+        */
+       printd("look for login: ");
+       for (;;) {
+               if (getline(buf, BUFSIZ, fd) == 0 || hup) {
+                       sleep(wait_time * tries);
+                       goto restart;
+               }
+               if (annex) {
+                       if (bcmp(buf, annex, strlen(annex)) == 0) {
+                               fprintf(wfd, "slip\r");
+                               printd("Sent \"slip\"\n");
+                               continue;
+                       }
+                       if (bcmp(&buf[1], "sername:", 8) == 0) {
+                               fprintf(wfd, "%s\r", argv[1]);
+                               printd("Sent login: %s\n", argv[1]);
+                               continue;
+                       }
+                       if (bcmp(&buf[1], "assword:", 8) == 0) {
+                               fprintf(wfd, "%s\r", argv[2]);
+                               printd("Sent password: %s\n", argv[2]);
+                               break;
+                       }
+               } else {
+                       if (bcmp(&buf[1], "ogin:", 5) == 0) {
+                               fprintf(wfd, "%s\r", argv[1]);
+                               printd("Sent login: %s\n", argv[1]);
+                               continue;
+                       }
+                       if (bcmp(&buf[1], "assword:", 8) == 0) {
+                               fprintf(wfd, "%s\r", argv[2]);
+                               printd("Sent password: %s\n", argv[2]);
+                               break;
+                       }
+               }
+       }
+       
+       /*
+        * Security hack.  Do not want private information such as the
+        * password and possible phone number to be left around.
+        * So we clobber the arguments.
+        */
+       for (ap = argv - optind + 1; ap < argv + 3; ap++)
+               for (cp = *ap; *cp != 0; cp++)
+                       *cp = '\0';
+
+       /*
+        * Attach
+        */
+       printd("setd");
+       disc = SLIPDISC;
+       if (ioctl(fd, TIOCSETD, &disc) < 0) {
+               perror("ioctl(TIOCSETD)");
+               syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n",
+                   argv[0]);
+               exit(1);
+       }
+       if (first && debug == 0) {
+               close(0);
+               close(1);
+               close(2);
+               (void) open("/dev/null", O_RDWR);
+               (void) dup2(0, 1);
+               (void) dup2(0, 2);
+       }
+       (void) system("ifconfig sl0 up");
+       printd(", ready\n");
+       if (!first)
+               syslog(LOG_INFO, "reconnected (%d tries).\n", tries);
+       first = 0;
+       tries = 0;
+       logged_in = 1;
+       while (hup == 0) {
+               sigpause(0L);
+               printd("sigpause return\n");
+       }
+       goto restart;
+}
+
+void
+sighup()
+{
+
+       printd("hup\n");
+       if (hup == 0 && logged_in)
+               syslog(LOG_INFO, "hangup signal\n");
+       hup = 1;
+}
+
+getline(buf, size, fd)
+       char *buf;
+       int size, fd;
+{
+       register int i;
+       int ret;
+
+       size--;
+       for (i = 0; i < size; i++) {
+               if (hup)
+                       return (0);
+               if ((ret = read(fd, &buf[i], 1)) == 1) {
+                       buf[i] &= 0177;
+                       if (buf[i] == '\r' || buf[i] == '\0')
+                               buf[i] = '\n';
+                       if (buf[i] != '\n' && buf[i] != ':')
+                               continue;
+                       buf[i + 1] = '\0';
+                       printd("Got %d: \"%s\"\n", i + 1, buf);
+                       return (i+1);
+               }
+               if (ret <= 0) {
+                       if (ret < 0)
+                               perror("getline: read");
+                       else
+                               fprintf(stderr, "read returned 0\n");
+                       buf[i] = '\0';
+                       printd("returning 0 after %d: \"%s\"\n", i, buf);
+                       return (0);
+               }
+       }
+       return (0);
+}
+
+usage()
+{
+       (void)fprintf(stderr,
+           "usage: startslip [-d] [-b speed] [-s string] [-A annexname] [-F flowcontrol] dev user passwd\n");
+       exit(1);
+}
diff --git a/stdethers.tproj/Makefile b/stdethers.tproj/Makefile
new file mode 100644 (file)
index 0000000..3ee9c9a
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = stdethers
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = stdethers.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble stdethers.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/stdethers.tproj/Makefile.postamble b/stdethers.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/stdethers.tproj/Makefile.preamble b/stdethers.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/stdethers.tproj/PB.project b/stdethers.tproj/PB.project
new file mode 100644 (file)
index 0000000..6379be0
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (stdethers.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, stdethers.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = stdethers; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/stdethers.tproj/stdethers.8 b/stdethers.tproj/stdethers.8
new file mode 100644 (file)
index 0000000..3740af7
--- /dev/null
@@ -0,0 +1,55 @@
+.\"    $OpenBSD: stdethers.8,v 1.3 1996/05/30 09:53:11 deraadt Exp $
+.\" Copyright (c) 1995 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd December 2, 1995
+.Dt STDETHERS 8
+.Os
+.Sh NAME
+.Nm stdethers
+.Nd a YP filter program
+.Sh SYNOPSIS
+.Nm stdethers
+.Op Ar file
+.Sh DESCRIPTION
+.Nm Stdethers
+is used to get ride of some unwanted information in file or stdin. This
+program is used by YP when creating some YP maps.
+.Pp
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Ar file
+Use this file as input instead of stdin.
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr ypserv 8 
+.Sh AUTHOR
+Mats O Jansson <moj@stacken.kth.se>
diff --git a/stdethers.tproj/stdethers.c b/stdethers.tproj/stdethers.c
new file mode 100644 (file)
index 0000000..f9ef339
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: stdethers.c,v 1.3 1997/09/11 19:47:33 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1995 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: stdethers.c,v 1.3 1997/09/11 19:47:33 deraadt Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+char *ProgramName = "stdethers";
+
+extern int   ether_line(char *, struct ether_addr *, char *);
+extern char *ether_ntoa(struct ether_addr *);
+
+#ifndef NTOA_FIX
+#define        NTOA(x) (char *)ether_ntoa(x)
+#else
+#define NTOA(x) (char *) working_ntoa((u_char *) x)
+
+/* As of 1995-12-02 NetBSD and OpenBSD has an SunOS 4 incompatible ether_ntoa.
+   The code in usr/lib/libc/net/ethers seems to do the correct thing
+   when asking YP but not when returning string from ether_ntoa.
+ */
+
+char *
+working_ntoa(e)
+       u_char  *e;
+{
+       static char a[] = "xx:xx:xx:xx:xx:xx";
+
+       sprintf(a, "%x:%x:%x:%x:%x:%x",
+               e[0], e[1], e[2], e[3], e[4], e[5]);
+       return a;
+}
+#endif
+
+static int read_line(fp, buf, size)
+FILE *fp;
+char *buf;
+int size;
+{
+       int done = 0;
+
+       do {
+               while (fgets(buf, size, fp)) {
+                       int len = strlen(buf);
+                       done += len;
+                       if (len > 1 && buf[len-2] == '\\' &&
+                                       buf[len-1] == '\n') {
+                               int ch;
+                               buf += len - 2;
+                               size -= len - 2;
+                               *buf = '\n'; buf[1] = '\0';
+                               /*
+                                * Skip leading white space on next line
+                                */
+                               while ((ch = getc(fp)) != EOF &&
+                                       isascii(ch) && isspace(ch))
+                                               ;
+                               (void) ungetc(ch, fp);
+                       } else {
+                               return done;
+                       }
+               }
+       } while (size > 0 && !feof(fp));
+
+       return done;
+}
+
+int
+main (argc,argv)
+int argc;
+char *argv[];
+{
+       FILE    *data_file;
+       char     data_line[1024];
+       int      usage = 0;
+       int      line_no = 0;
+       int      len;
+       char    *p,*k,*v;
+       struct ether_addr eth_addr;
+       char     hostname[256];
+       
+       if (argc > 2) {
+               usage++;
+       }
+       
+       if (usage) {
+               fprintf(stderr,
+                       "usage: %s [file]\n",
+                       ProgramName);
+               exit(1);
+       }
+       
+       if (argc == 2) {
+               data_file = fopen(argv[1], "r");
+               if (data_file == NULL) {
+                       fprintf(stderr,
+                               "%s: can't open %s\n",
+                               ProgramName,
+                               argv[1]);
+                       exit(1);
+               }
+       } else {
+               data_file = stdin;
+       }
+       
+       while (read_line(data_file,data_line,sizeof(data_line))) {
+               
+               line_no++;
+               len = strlen(data_line);
+               
+               if (len > 0) {
+                       if (data_line[0] == '#')
+                               continue;
+               }
+               
+               /*
+                * Check if we have the whole line
+                */ 
+               
+               if (data_line[len-1] != '\n') {
+                       if (argc == 2) {
+                               fprintf(stderr,
+                                       "line %d in \"%s\" is too long",
+                                       line_no, argv[1]);
+                       } else {
+                               fprintf(stderr,
+                                       "line %d in \"stdin\" is too long",
+                                       line_no);
+                       }
+               } else {
+                       data_line[len-1] = '\0';
+               }
+               
+               p = (char *) &data_line;
+               
+               k  = p;                         /* save start of key */
+               while (!isspace(*p)) { p++; };  /* find first "space" */
+               while (isspace(*p)) { p++; };   /* move over "space" */
+               
+               v = p;                          /* save start of value */
+               while(*p != '\0') { p++; };     /* find end of string */
+               
+               if (ether_line(data_line, &eth_addr, hostname) == 0) {
+                       fprintf(stdout, "%s\t%s\n",
+                               NTOA(&eth_addr),
+                               hostname);
+               } else {
+                       fprintf(stderr,
+                               "%s: ignoring line %d: \"%s\"\n",
+                               ProgramName,
+                               line_no,
+                               data_line);
+               }
+       }
+       
+       return(0);
+       
+}
diff --git a/stdhosts.tproj/Makefile b/stdhosts.tproj/Makefile
new file mode 100644 (file)
index 0000000..600fddf
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = stdhosts
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = stdhosts.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble stdhosts.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/stdhosts.tproj/Makefile.postamble b/stdhosts.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/stdhosts.tproj/Makefile.preamble b/stdhosts.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/stdhosts.tproj/PB.project b/stdhosts.tproj/PB.project
new file mode 100644 (file)
index 0000000..ba79c4b
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (stdhosts.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, stdhosts.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = stdhosts; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/stdhosts.tproj/stdhosts.8 b/stdhosts.tproj/stdhosts.8
new file mode 100644 (file)
index 0000000..6cd5540
--- /dev/null
@@ -0,0 +1,55 @@
+.\"    $OpenBSD: stdhosts.8,v 1.4 1996/06/26 21:26:36 maja Exp $
+.\" Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd August 25, 1994
+.Dt STDHOSTS 8
+.Os
+.Sh NAME
+.Nm stdhosts
+.Nd a YP filter program
+.Sh SYNOPSIS
+.Nm stdhosts
+.Op Ar file
+.Sh DESCRIPTION
+.Nm Stdhosts
+is used to get ride of some unwanted information in file or stdin. This
+program is used by YP when creating some YP maps.
+.Pp
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Ar file
+Use this file as input instead of stdin.
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr ypserv 8 
+.Sh AUTHOR
+Mats O Jansson <moj@stacken.kth.se>
diff --git a/stdhosts.tproj/stdhosts.c b/stdhosts.tproj/stdhosts.c
new file mode 100644 (file)
index 0000000..3406558
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: stdhosts.c,v 1.4 1997/09/11 19:47:35 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: stdhosts.c,v 1.4 1997/09/11 19:47:35 deraadt Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+static int read_line(fp, buf, size)
+FILE *fp;
+char *buf;
+int size;
+{
+       int done = 0;
+
+       do {
+               while (fgets(buf, size, fp)) {
+                       int len = strlen(buf);
+                       done += len;
+                       if (len > 1 && buf[len-2] == '\\' &&
+                                       buf[len-1] == '\n') {
+                               int ch;
+                               buf += len - 2;
+                               size -= len - 2;
+                               *buf = '\n'; buf[1] = '\0';
+                               /*
+                                * Skip leading white space on next line
+                                */
+                               while ((ch = getc(fp)) != EOF &&
+                                       isascii(ch) && isspace(ch))
+                                               ;
+                               (void) ungetc(ch, fp);
+                       } else {
+                               return done;
+                       }
+               }
+       } while (size > 0 && !feof(fp));
+
+       return done;
+}
+
+int
+main (argc,argv)
+int argc;
+char *argv[];
+{
+  FILE *data_file;
+  char  data_line[1024];
+  int   usage = 0;
+  int   line_no = 0;
+  int   len;
+  char *p,*k,*v;
+  struct in_addr host_addr;
+
+  if (argc > 2) {
+    usage++;
+  }
+
+  if (usage) {
+    fprintf(stderr,
+           "%s",
+           "usage: stdhosts [file]\n");
+    exit(1);
+  }
+
+  if (argc == 2) {
+    data_file = fopen(argv[argc-1], "r");
+  } else {
+    data_file = stdin;
+  }
+  
+  while (read_line(data_file,data_line,sizeof(data_line))) {
+    
+    line_no++;
+    len = strlen(data_line);
+    
+    if (len > 0) {
+      if (data_line[0] == '#')
+       continue;
+    }
+
+    /*
+     * Check if we have the whole line
+     */ 
+
+    if (data_line[len-1] != '\n') {
+      if (argc == 2) {
+       fprintf(stderr, "line %d in \"%s\" is too long", line_no, argv[1]);
+      } else {
+       fprintf(stderr, "line %d in \"stdin\" is too long", line_no);
+      }
+    } else {
+      data_line[len-1] = '\0';
+    }
+
+    p = (char *) &data_line;
+
+    k  = p;                                    /* save start of key */
+    while (!isspace(*p)) { p++; };             /* find first "space" */
+    while (isspace(*p)) { *p = '\0'; p++; };   /* replace space with <NUL> */
+    
+    v = p;                                     /* save start of value */
+    while(*p != '\0') { p++; };                        /* find end of string */
+
+    (void)inet_aton(k,&host_addr);
+    printf("%s %s\n",inet_ntoa(host_addr),v);
+
+  }
+
+  return(0);
+  
+}
diff --git a/syslogd.tproj/Makefile b/syslogd.tproj/Makefile
new file mode 100644 (file)
index 0000000..9eae816
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = syslogd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = syslogd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble syslogd.8\
+            syslog.conf.5
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/syslogd.tproj/Makefile.postamble b/syslogd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..60da20d
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
+VPATH += :../wall.tproj
diff --git a/syslogd.tproj/Makefile.preamble b/syslogd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d2e854c
--- /dev/null
@@ -0,0 +1,115 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+OTHER_OFILES = ttymsg.o
+
+-include ../Makefile.include
diff --git a/syslogd.tproj/PB.project b/syslogd.tproj/PB.project
new file mode 100644 (file)
index 0000000..45a56f3
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pathnames.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (syslogd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, syslogd.8, syslog.conf.5); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = syslogd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/syslogd.tproj/pathnames.h b/syslogd.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..b03e65d
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#define        _PATH_KLOG      "/dev/klog"
+#define        _PATH_LOGCONF   "/etc/syslog.conf"
+#define        _PATH_LOGPID    "/var/run/syslog.pid"
diff --git a/syslogd.tproj/syslog.conf.5 b/syslogd.tproj/syslog.conf.5
new file mode 100644 (file)
index 0000000..b19e75d
--- /dev/null
@@ -0,0 +1,224 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)syslog.conf.5      8.1 (Berkeley) 6/9/93
+.\"
+.Dd June 9, 1993
+.Dt SYSLOG.CONF 5
+.Os
+.Sh NAME
+.Nm syslog.conf
+.Nd
+.Xr syslogd 8
+configuration file
+.Sh DESCRIPTION
+The
+.Nm syslog.conf
+file is the configuration file for the
+.Xr syslogd 8
+program.
+It consists of lines with two fields: the
+.Em selector
+field which specifies the types of messages and priorities to which the
+line applies, and an
+.Em action
+field which specifies the action to be taken if a message
+.Xr syslogd
+receives matches the selection criteria.
+The
+.Em selector
+field is separated from the
+.Em action
+field by one or more tab characters.
+.Pp
+The
+.Em Selectors
+function
+are encoded as a
+.Em facility ,
+a period (``.''), and a
+.Em level ,
+with no intervening white-space.
+Both the
+.Em facility
+and the
+.Em level
+are case insensitive.
+.Pp
+The
+.Em facility
+describes the part of the system generating the message, and is one of
+the following keywords: auth, authpriv, cron, daemon, kern, lpr, mail,
+mark, news, syslog, user, uucp and local0 through local7.
+These keywords (with the exception of mark) correspond to the
+similar
+.Dq Dv LOG_
+values specified to the
+.Xr openlog 3
+and
+.Xr syslog 3
+library routines.
+.Pp
+The
+.Em level
+describes the severity of the message, and is a keyword from the
+following ordered list (higher to lower): emerg, alert, crit, err,
+warning, notice and debug.
+These keywords correspond to the
+similar
+.Pq Dv LOG_
+values specified to the
+.Xr syslog
+library routine.
+.Pp
+See
+.Xr syslog 3
+for a further descriptions of both the
+.Em facility
+and
+.Em level
+keywords and their significance.
+.Pp
+If a received message matches the specified
+.Em facility
+and is of the specified
+.Em level
+.Em (or a higher level) ,
+the action specified in the
+.Em action
+field will be taken.
+.Pp
+Multiple
+.Em selectors
+may be specified for a single
+.Em action
+by separating them with semicolon (``;'') characters.
+It is important to note, however, that each
+.Em selector
+can modify the ones preceding it.
+.Pp
+Multiple
+.Em facilities
+may be specified for a single
+.Em level
+by separating them with comma (``,'') characters.
+.Pp
+An asterisk (``*'') can be used to specify all
+.Em facilities
+or all
+.Em levels .
+.Pp
+The special
+.Em facility
+``mark'' receives a message at priority ``info'' every 20 minutes
+(see
+.Xr syslogd 8 ) .
+This is not enabled by a
+.Em facility
+field containing an asterisk.
+.Pp
+The special
+.Em level
+``none'' disables a particular
+.Em facility .
+.Pp
+The
+.Em action
+field of each line specifies the action to be taken when the
+.Em selector
+field selects a message.
+There are four forms:
+.Bl -bullet
+.It
+A pathname (beginning with a leading slash).
+Selected messages are appended to the file.
+.It
+A hostname (preceded by an at (``@'') sign).
+Selected messages are forwarded to the
+.Xr syslogd
+program on the named host.
+.It
+A comma separated list of users.
+Selected messages are written to those users
+if they are logged in.
+.It
+An asterisk.
+Selected messages are written to all logged-in users.
+.El
+.Pp
+Blank lines and lines whose first non-blank character is a hash (``#'')
+character are ignored.
+.Sh EXAMPLES
+.Pp
+A configuration file might appear as follows:
+.Bd -literal
+# Log all kernel messages, authentication messages of
+# level notice or higher and anything of level err or
+# higher to the console.
+# Don't log private authentication messages!
+*.err;kern.*;auth.notice;authpriv.none /dev/console
+
+# Log anything (except mail) of level info or higher.
+# Don't log private authentication messages!
+*.info;mail.none;authpriv.none         /var/log/messages
+
+# The authpriv file has restricted access.
+authpriv.*                                             /var/log/secure
+
+# Log all the mail messages in one place.
+mail.*                                                 /var/log/maillog
+
+# Everybody gets emergency messages, plus log them on another
+# machine.
+*.emerg                                                        *
+*.emerg                                                        @arpa.berkeley.edu
+
+# Root and Eric get alert and higher messages.
+*.alert                                                        root,eric
+
+# Save mail and news errors of level err and higher in a
+# special file.
+uucp,news.crit                                         /var/log/spoolerr
+.Ed
+.Sh FILES
+.Bl -tag -width /etc/syslog.conf -compact
+.It Pa /etc/syslog.conf
+The
+.Xr syslogd 8
+configuration file.
+.El
+.Sh BUGS
+The effects of multiple selectors are sometimes not intuitive.
+For example ``mail.crit,*.err'' will select ``mail'' facility messages at
+the level of ``err'' or higher, not at the level of ``crit'' or higher.
+.Sh SEE ALSO
+.Xr syslog 3 ,
+.Xr syslogd 8
diff --git a/syslogd.tproj/syslogd.8 b/syslogd.tproj/syslogd.8
new file mode 100644 (file)
index 0000000..f16297b
--- /dev/null
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1983, 1986, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)syslogd.8  8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt SYSLOGD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm syslogd
+.Nd log systems messages
+.Sh SYNOPSIS
+.Nm syslogd
+.Op Fl f Ar config_file
+.Op Fl m Ar mark_interval
+.Op Fl p Ar log_socket
+.Sh DESCRIPTION
+.Nm Syslogd
+reads and logs messages to the system console, log files, other
+machines and/or users as specified by its configuration file.
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl f
+Specify the pathname of an alternate configuration file;
+the default is
+.Pa /etc/syslog.conf .
+.It Fl m
+Select the number of minutes between ``mark'' messages;
+the default is 20 minutes.
+.It Fl p
+Specify the pathname of an alternate log socket;
+the default is
+.Pa /var/run/syslog .
+.El
+.Pp
+.Nm Syslogd
+reads its configuration file when it starts up and whenever it
+receives a hangup signal.
+For information on the format of the configuration file,
+see
+.Xr syslog.conf 5 .
+.Pp
+.Nm Syslogd
+reads messages from the
+.Tn UNIX
+domain socket
+.Pa /var/run/syslog ,
+from an Internet domain socket specified in
+.Pa /etc/services ,
+and from the special device
+.Pa /dev/klog
+(to read kernel messages).
+.Pp
+.Nm Syslogd
+creates the file
+.Pa /var/run/syslog.pid ,
+and stores its process
+id there.
+This can be used to kill or reconfigure
+.Nm syslogd .
+.Pp
+The message sent to
+.Nm syslogd
+should consist of a single line.
+The message can contain a priority code, which should be a preceding
+decimal number in angle braces, for example,
+.Sq Aq 5.
+This priority code should map into the priorities defined in the
+include file
+.Aq Pa sys/syslog.h .
+.Sh FILES
+.Bl -tag -width /var/run/syslog.pid -compact
+.It Pa /etc/syslog.conf
+The configuration file.
+.It Pa /var/run/syslog.pid
+The process id of current
+.Nm syslogd .
+.It Pa /var/run/syslog
+Name of the
+.Tn UNIX
+domain datagram log socket.
+.It Pa /dev/klog
+The kernel log device.
+.El
+.Sh SEE ALSO
+.Xr logger 1 ,
+.Xr syslog 3 ,
+.Xr services 5 ,
+.Xr syslog.conf 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/syslogd.tproj/syslogd.c b/syslogd.tproj/syslogd.c
new file mode 100644 (file)
index 0000000..27cb99b
--- /dev/null
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)syslogd.c  8.3 (Berkeley) 4/4/94";
+#endif /* not lint */
+
+/*
+ *  syslogd -- log system messages
+ *
+ * This program implements a system log. It takes a series of lines.
+ * Each line may have a priority, signified as "<n>" as
+ * the first characters of the line.  If this is
+ * not present, a default priority is used.
+ *
+ * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will
+ * cause it to reread its configuration file.
+ *
+ * Defined Constants:
+ *
+ * MAXLINE -- the maximimum line length that can be handled.
+ * DEFUPRI -- the default priority for user messages
+ * DEFSPRI -- the default priority for kernel messages
+ *
+ * Author: Eric Allman
+ * extensive changes by Ralph Campbell
+ * more extensive changes by Eric Allman (again)
+ */
+
+#define        MAXLINE         1024            /* maximum line length */
+#define        MAXSVLINE       120             /* maximum saved line length */
+#define DEFUPRI                (LOG_USER|LOG_NOTICE)
+#define DEFSPRI                (LOG_KERN|LOG_CRIT)
+#define TIMERINTVL     30              /* interval for checking flush, mark */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/msgbuf.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#include "pathnames.h"
+
+#define SYSLOG_NAMES
+#include <sys/syslog.h>
+
+char   *LogName = _PATH_LOG;
+char   *ConfFile = _PATH_LOGCONF;
+char   *PidFile = _PATH_LOGPID;
+char   ctty[] = _PATH_CONSOLE;
+
+#define FDMASK(fd)     (1 << (fd))
+
+#define        dprintf         if (Debug) printf
+
+#define MAXUNAMES      20      /* maximum number of user names */
+
+/*
+ * Flags to logmsg().
+ */
+
+#define IGN_CONS       0x001   /* don't print on console */
+#define SYNC_FILE      0x002   /* do fsync on file after printing */
+#define ADDDATE                0x004   /* add a date to the message */
+#define MARK           0x008   /* this message is a mark */
+
+/*
+ * This structure represents the files that will have log
+ * copies printed.
+ */
+
+struct filed {
+       struct  filed *f_next;          /* next in linked list */
+       short   f_type;                 /* entry type, see below */
+       short   f_file;                 /* file descriptor */
+       time_t  f_time;                 /* time this was last written */
+       u_char  f_pmask[LOG_NFACILITIES+1];     /* priority mask */
+       union {
+               char    f_uname[MAXUNAMES][UT_NAMESIZE+1];
+               struct {
+                       char    f_hname[MAXHOSTNAMELEN+1];
+                       struct sockaddr_in      f_addr;
+               } f_forw;               /* forwarding address */
+               char    f_fname[MAXPATHLEN];
+       } f_un;
+       char    f_prevline[MAXSVLINE];          /* last message logged */
+       char    f_lasttime[16];                 /* time of last occurrence */
+       char    f_prevhost[MAXHOSTNAMELEN+1];   /* host from which recd. */
+       int     f_prevpri;                      /* pri of f_prevline */
+       int     f_prevlen;                      /* length of f_prevline */
+       int     f_prevcount;                    /* repetition cnt of prevline */
+       int     f_repeatcount;                  /* number of "repeated" msgs */
+};
+
+/*
+ * Intervals at which we flush out "message repeated" messages,
+ * in seconds after previous message is logged.  After each flush,
+ * we move to the next interval until we reach the largest.
+ */
+int    repeatinterval[] = { 30, 120, 600 };    /* # of secs before flush */
+#define        MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
+#define        REPEATTIME(f)   ((f)->f_time + repeatinterval[(f)->f_repeatcount])
+#define        BACKOFF(f)      { if (++(f)->f_repeatcount > MAXREPEAT) \
+                                (f)->f_repeatcount = MAXREPEAT; \
+                       }
+
+/* values for f_type */
+#define F_UNUSED       0               /* unused entry */
+#define F_FILE         1               /* regular file */
+#define F_TTY          2               /* terminal */
+#define F_CONSOLE      3               /* console terminal */
+#define F_FORW         4               /* remote machine */
+#define F_USERS                5               /* list of users */
+#define F_WALL         6               /* everyone logged on */
+
+char   *TypeNames[7] = {
+       "UNUSED",       "FILE",         "TTY",          "CONSOLE",
+       "FORW",         "USERS",        "WALL"
+};
+
+struct filed *Files;
+struct filed consfile;
+
+int    Debug = 0;              /* debug flag */
+int    Insecure = 0;           /* insecure flag */
+char   LocalHostName[MAXHOSTNAMELEN+1];        /* our hostname */
+char   *LocalDomain;           /* our local domain name */
+int    InetInuse = 0;          /* non-zero if INET sockets are being used */
+int    finet;                  /* Internet datagram socket */
+int    LogPort;                /* port number for INET connections */
+int    Initialized = 0;        /* set when we have initialized ourselves */
+int    MarkInterval = 20 * 60; /* interval between marks in seconds */
+int    MarkSeq = 0;            /* mark sequence number */
+
+void   cfline __P((char *, struct filed *));
+char   *cvthname __P((struct sockaddr_in *));
+int    decode __P((const char *, CODE *));
+void   die __P((int));
+void   domark __P((int));
+void   fprintlog __P((struct filed *, int, char *));
+void   init __P((int));
+void   logerror __P((char *));
+void   logmsg __P((int, char *, char *, int));
+void   printline __P((char *, char *));
+void   printsys __P((char *));
+void   reapchild __P((int));
+char   *ttymsg __P((struct iovec *, int, char *, int));
+void   usage __P((void));
+void   wallmsg __P((struct filed *, struct iovec *));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int ch, funix, i, inetm, fklog, klogm, len;
+       struct sockaddr_un sunx, fromunix;
+       struct sockaddr_in sin, frominet;
+       FILE *fp;
+       char *p, line[MSG_BSIZE + 1];
+
+       while ((ch = getopt(argc, argv, "duf:m:p:")) != EOF)
+               switch(ch) {
+               case 'd':               /* debug */
+                       Debug++;
+                       break;
+               case 'u':               /* insecure */
+                       Insecure++;
+                       break;
+               case 'f':               /* configuration file */
+                       ConfFile = optarg;
+                       break;
+               case 'm':               /* mark interval */
+                       MarkInterval = atoi(optarg) * 60;
+                       break;
+               case 'p':               /* path */
+                       LogName = optarg;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       if ((argc -= optind) != 0)
+               usage();
+
+       if (!Debug)
+               (void)daemon(0, 0);
+       else
+               setlinebuf(stdout);
+
+       consfile.f_type = F_CONSOLE;
+       (void)strcpy(consfile.f_un.f_fname, ctty);
+       (void)gethostname(LocalHostName, sizeof(LocalHostName));
+       if ((p = strchr(LocalHostName, '.')) != NULL) {
+               *p++ = '\0';
+               LocalDomain = p;
+       } else
+               LocalDomain = "";
+       (void)signal(SIGTERM, die);
+       (void)signal(SIGINT, Debug ? die : SIG_IGN);
+       (void)signal(SIGQUIT, Debug ? die : SIG_IGN);
+       (void)signal(SIGCHLD, reapchild);
+       (void)signal(SIGALRM, domark);
+       (void)alarm(TIMERINTVL);
+       (void)unlink(LogName);
+
+#ifndef SUN_LEN
+#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
+#endif
+       memset(&sunx, 0, sizeof(sunx));
+       sunx.sun_family = AF_UNIX;
+       (void)strncpy(sunx.sun_path, LogName, sizeof(sunx.sun_path));
+       funix = socket(AF_UNIX, SOCK_DGRAM, 0);
+       if (funix < 0 ||
+           bind(funix, (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 ||
+           chmod(LogName, 0666) < 0) {
+               (void) snprintf(line, sizeof line, "cannot create %s", LogName);
+               logerror(line);
+               dprintf("cannot create %s (%d)\n", LogName, errno);
+               die(0);
+       }
+       finet = socket(AF_INET, SOCK_DGRAM, 0);
+       inetm = 0;
+       if (finet >= 0) {
+               struct servent *sp;
+
+               sp = getservbyname("syslog", "udp");
+               if (sp == NULL) {
+                       errno = 0;
+                       logerror("syslog/udp: unknown service");
+                       die(0);
+               }
+               memset(&sin, 0, sizeof(sin));
+               sin.sin_family = AF_INET;
+               sin.sin_port = LogPort = sp->s_port;
+               if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+                       logerror("bind");
+                       if (!Debug)
+                               die(0);
+               } else {
+                       inetm = FDMASK(finet);
+                       InetInuse = 1;
+               }
+       }
+       if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0)
+               klogm = FDMASK(fklog);
+       else {
+               dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
+               klogm = 0;
+       }
+
+       /* tuck my process id away */
+       fp = fopen(PidFile, "w");
+       if (fp != NULL) {
+               fprintf(fp, "%d\n", getpid());
+               (void) fclose(fp);
+       }
+
+       dprintf("off & running....\n");
+
+       init(0);
+       (void)signal(SIGHUP, init);
+
+       for (;;) {
+               int nfds, readfds = FDMASK(funix) | inetm | klogm;
+
+               dprintf("readfds = %#x\n", readfds);
+               nfds = select(20, (fd_set *)&readfds, (fd_set *)NULL,
+                   (fd_set *)NULL, (struct timeval *)NULL);
+               if (nfds == 0)
+                       continue;
+               if (nfds < 0) {
+                       if (errno != EINTR)
+                               logerror("select");
+                       continue;
+               }
+               dprintf("got a message (%d, %#x)\n", nfds, readfds);
+               if (readfds & klogm) {
+                       i = read(fklog, line, sizeof(line) - 1);
+                       if (i > 0) {
+                               line[i] = '\0';
+                               printsys(line);
+                       } else if (i < 0 && errno != EINTR) {
+                               logerror("klog");
+                               fklog = -1;
+                               klogm = 0;
+                       }
+               }
+               if (readfds & FDMASK(funix)) {
+                       len = sizeof(fromunix);
+                       i = recvfrom(funix, line, MAXLINE, 0,
+                           (struct sockaddr *)&fromunix, &len);
+                       if (i > 0) {
+                               line[i] = '\0';
+                               printline(LocalHostName, line);
+                       } else if (i < 0 && errno != EINTR)
+                               logerror("recvfrom unix");
+               }
+               if (readfds & inetm) {
+                       len = sizeof(frominet);
+                       i = recvfrom(finet, line, MAXLINE, 0,
+                           (struct sockaddr *)&frominet, &len);
+                       if (Insecure) {
+                               if (i > 0) {
+                                       line[i] = '\0';
+                                       printline(cvthname(&frominet), line);
+                               } else if (i < 0 && errno != EINTR)
+                                       logerror("recvfrom inet");
+                       }
+               } 
+       }
+}
+
+void
+usage()
+{
+
+       (void)fprintf(stderr,
+           "usage: syslogd [-f conffile] [-m markinterval] [-p logpath]\n");
+       exit(1);
+}
+
+/*
+ * Take a raw input line, decode the message, and print the message
+ * on the appropriate log files.
+ */
+void
+printline(hname, msg)
+       char *hname;
+       char *msg;
+{
+       int c, pri;
+       char *p, *q, line[MAXLINE + 1];
+
+       /* test for special codes */
+       pri = DEFUPRI;
+       p = msg;
+       if (*p == '<') {
+               pri = 0;
+               while (isdigit(*++p))
+                       pri = 10 * pri + (*p - '0');
+               if (*p == '>')
+                       ++p;
+       }
+       if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
+               pri = DEFUPRI;
+
+       /* don't allow users to log kernel messages */
+       if (LOG_FAC(pri) == LOG_KERN)
+               pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
+
+       q = line;
+
+       while ((c = *p++) != '\0' &&
+           q < &line[sizeof(line) - 2]) {
+               c &= 0177;
+               if (iscntrl(c))
+                       if (c == '\n')
+                               *q++ = ' ';
+                       else if (c == '\t')
+                               *q++ = '\t';
+                       else {
+                               *q++ = '^';
+                               *q++ = c ^ 0100;
+                       }
+               else
+                       *q++ = c;
+       }
+       *q = '\0';
+
+       logmsg(pri, line, hname, 0);
+}
+
+/*
+ * Take a raw input line from /dev/klog, split and format similar to syslog().
+ */
+void
+printsys(msg)
+       char *msg;
+{
+       int c, pri, flags;
+       char *lp, *p, *q, line[MAXLINE + 1];
+
+       (void)strcpy(line, "mach_kernel: ");
+       lp = line + strlen(line);
+       for (p = msg; *p != '\0'; ) {
+               flags = SYNC_FILE | ADDDATE;    /* fsync file after write */
+               pri = DEFSPRI;
+               if (*p == '<') {
+                       pri = 0;
+                       while (isdigit(*++p))
+                               pri = 10 * pri + (*p - '0');
+                       if (*p == '>')
+                               ++p;
+               } else {
+                       /* kernel printf's come out on console */
+                       flags |= IGN_CONS;
+               }
+               if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
+                       pri = DEFSPRI;
+               q = lp;
+               while (*p != '\0' && (c = *p++) != '\n' &&
+                   q < &line[MAXLINE])
+                       *q++ = c;
+               *q = '\0';
+               logmsg(pri, line, LocalHostName, flags);
+       }
+}
+
+time_t now;
+
+/*
+ * Log a message to the appropriate log files, users, etc. based on
+ * the priority.
+ */
+void
+logmsg(pri, msg, from, flags)
+       int pri;
+       char *msg, *from;
+       int flags;
+{
+       struct filed *f;
+       int fac, msglen, omask, prilev;
+       char *timestamp;
+
+       dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
+           pri, flags, from, msg);
+
+       omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
+
+       /*
+        * Check to see if msg looks non-standard.
+        */
+       msglen = strlen(msg);
+       if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
+           msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
+               flags |= ADDDATE;
+
+       (void)time(&now);
+       if (flags & ADDDATE)
+               timestamp = ctime(&now) + 4;
+       else {
+               timestamp = msg;
+               msg += 16;
+               msglen -= 16;
+       }
+
+       /* extract facility and priority level */
+       if (flags & MARK)
+               fac = LOG_NFACILITIES;
+       else
+               fac = LOG_FAC(pri);
+       prilev = LOG_PRI(pri);
+
+       /* log the message to the particular outputs */
+       if (!Initialized) {
+               f = &consfile;
+               f->f_file = open(ctty, O_WRONLY, 0);
+
+               if (f->f_file >= 0) {
+                       fprintlog(f, flags, msg);
+                       (void)close(f->f_file);
+               }
+               (void)sigsetmask(omask);
+               return;
+       }
+       for (f = Files; f; f = f->f_next) {
+               /* skip messages that are incorrect priority */
+               if (f->f_pmask[fac] < prilev ||
+                   f->f_pmask[fac] == INTERNAL_NOPRI)
+                       continue;
+
+               if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
+                       continue;
+
+               /* don't output marks to recently written files */
+               if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
+                       continue;
+
+               /*
+                * suppress duplicate lines to this file
+                */
+               if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
+                   !strcmp(msg, f->f_prevline) &&
+                   !strcmp(from, f->f_prevhost)) {
+                       (void)strncpy(f->f_lasttime, timestamp, 15);
+                       f->f_prevcount++;
+                       dprintf("msg repeated %d times, %ld sec of %d\n",
+                           f->f_prevcount, now - f->f_time,
+                           repeatinterval[f->f_repeatcount]);
+                       /*
+                        * If domark would have logged this by now,
+                        * flush it now (so we don't hold isolated messages),
+                        * but back off so we'll flush less often
+                        * in the future.
+                        */
+                       if (now > REPEATTIME(f)) {
+                               fprintlog(f, flags, (char *)NULL);
+                               BACKOFF(f);
+                       }
+               } else {
+                       /* new line, save it */
+                       if (f->f_prevcount)
+                               fprintlog(f, 0, (char *)NULL);
+                       f->f_repeatcount = 0;
+                       (void)strncpy(f->f_lasttime, timestamp, 15);
+                       (void)strncpy(f->f_prevhost, from,
+                                       sizeof(f->f_prevhost));
+                       if (msglen < MAXSVLINE) {
+                               f->f_prevlen = msglen;
+                               f->f_prevpri = pri;
+                               (void)strcpy(f->f_prevline, msg);
+                               fprintlog(f, flags, (char *)NULL);
+                       } else {
+                               f->f_prevline[0] = 0;
+                               f->f_prevlen = 0;
+                               fprintlog(f, flags, msg);
+                       }
+               }
+       }
+       (void)sigsetmask(omask);
+}
+
+void
+fprintlog(f, flags, msg)
+       struct filed *f;
+       int flags;
+       char *msg;
+{
+       struct iovec iov[6];
+       struct iovec *v;
+       int l;
+       char line[MAXLINE + 1], repbuf[80], greetings[200];
+
+       v = iov;
+       if (f->f_type == F_WALL) {
+               v->iov_base = greetings;
+               v->iov_len = snprintf(greetings, sizeof greetings, 
+                   "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
+                   f->f_prevhost, ctime(&now));
+               v++;
+               v->iov_base = "";
+               v->iov_len = 0;
+               v++;
+       } else {
+               v->iov_base = f->f_lasttime;
+               v->iov_len = 15;
+               v++;
+               v->iov_base = " ";
+               v->iov_len = 1;
+               v++;
+       }
+       v->iov_base = f->f_prevhost;
+       v->iov_len = strlen(v->iov_base);
+       v++;
+       v->iov_base = " ";
+       v->iov_len = 1;
+       v++;
+
+       if (msg) {
+               v->iov_base = msg;
+               v->iov_len = strlen(msg);
+       } else if (f->f_prevcount > 1) {
+               v->iov_base = repbuf;
+               v->iov_len = snprintf(repbuf, sizeof repbuf, "last message repeated %d times",
+                   f->f_prevcount);
+       } else {
+               v->iov_base = f->f_prevline;
+               v->iov_len = f->f_prevlen;
+       }
+       v++;
+
+       dprintf("Logging to %s", TypeNames[f->f_type]);
+       f->f_time = now;
+
+       switch (f->f_type) {
+       case F_UNUSED:
+               dprintf("\n");
+               break;
+
+       case F_FORW:
+               dprintf(" %s\n", f->f_un.f_forw.f_hname);
+               l = snprintf(line, sizeof line, "<%d>%.15s %s", f->f_prevpri,
+                   iov[0].iov_base, iov[4].iov_base);
+               if (l > MAXLINE)
+                       l = MAXLINE;
+               if (sendto(finet, line, l, 0,
+                   (struct sockaddr *)&f->f_un.f_forw.f_addr,
+                   sizeof(f->f_un.f_forw.f_addr)) != l) {
+                       int e = errno;
+                       (void)close(f->f_file);
+                       f->f_type = F_UNUSED;
+                       errno = e;
+                       logerror("sendto");
+               }
+               break;
+
+       case F_CONSOLE:
+               if (flags & IGN_CONS) {
+                       dprintf(" (ignored)\n");
+                       break;
+               }
+               /* FALLTHROUGH */
+
+       case F_TTY:
+       case F_FILE:
+               dprintf(" %s\n", f->f_un.f_fname);
+               if (f->f_type != F_FILE) {
+                       v->iov_base = "\r\n";
+                       v->iov_len = 2;
+               } else {
+                       v->iov_base = "\n";
+                       v->iov_len = 1;
+               }
+       again:
+               if (writev(f->f_file, iov, 6) < 0) {
+                       int e = errno;
+                       (void)close(f->f_file);
+                       /*
+                        * Check for errors on TTY's due to loss of tty
+                        */
+                       if ((e == EIO || e == EBADF) && f->f_type != F_FILE) {
+                               f->f_file = open(f->f_un.f_fname,
+                                   O_WRONLY|O_APPEND, 0);
+                               if (f->f_file < 0) {
+                                       f->f_type = F_UNUSED;
+                                       logerror(f->f_un.f_fname);
+                               } else
+                                       goto again;
+                       } else {
+                               f->f_type = F_UNUSED;
+                               errno = e;
+                               logerror(f->f_un.f_fname);
+                       }
+               } else if (flags & SYNC_FILE)
+                       (void)fsync(f->f_file);
+               break;
+
+       case F_USERS:
+       case F_WALL:
+               dprintf("\n");
+               v->iov_base = "\r\n";
+               v->iov_len = 2;
+               wallmsg(f, iov);
+               break;
+       }
+       f->f_prevcount = 0;
+}
+
+/*
+ *  WALLMSG -- Write a message to the world at large
+ *
+ *     Write the specified message to either the entire
+ *     world, or a list of approved users.
+ */
+void
+wallmsg(f, iov)
+       struct filed *f;
+       struct iovec *iov;
+{
+       static int reenter;                     /* avoid calling ourselves */
+       FILE *uf;
+       struct utmp ut;
+       int i;
+       char *p;
+       char line[sizeof(ut.ut_line) + 1];
+
+       if (reenter++)
+               return;
+       if ((uf = fopen(_PATH_UTMP, "r")) == NULL) {
+               logerror(_PATH_UTMP);
+               reenter = 0;
+               return;
+       }
+       /* NOSTRICT */
+       while (fread((char *)&ut, sizeof(ut), 1, uf) == 1) {
+               if (ut.ut_name[0] == '\0')
+                       continue;
+               strncpy(line, ut.ut_line, sizeof(ut.ut_line));
+               line[sizeof(ut.ut_line)] = '\0';
+               if (f->f_type == F_WALL) {
+                       if ((p = ttymsg(iov, 6, line, 60*5)) != NULL) {
+                               errno = 0;      /* already in msg */
+                               logerror(p);
+                       }
+                       continue;
+               }
+               /* should we send the message to this user? */
+               for (i = 0; i < MAXUNAMES; i++) {
+                       if (!f->f_un.f_uname[i][0])
+                               break;
+                       if (!strncmp(f->f_un.f_uname[i], ut.ut_name,
+                           UT_NAMESIZE)) {
+                               if ((p = ttymsg(iov, 6, line, 60*5)) != NULL) {
+                                       errno = 0;      /* already in msg */
+                                       logerror(p);
+                               }
+                               break;
+                       }
+               }
+       }
+       (void)fclose(uf);
+       reenter = 0;
+}
+
+void
+reapchild(signo)
+       int signo;
+{
+       union wait status;
+
+       while (wait3((int *)&status, WNOHANG, (struct rusage *)NULL) > 0)
+               ;
+}
+
+/*
+ * Return a printable representation of a host address.
+ */
+char *
+cvthname(f)
+       struct sockaddr_in *f;
+{
+       struct hostent *hp;
+       char *p;
+
+       dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr));
+
+       if (f->sin_family != AF_INET) {
+               dprintf("Malformed from address\n");
+               return ("???");
+       }
+       hp = gethostbyaddr((char *)&f->sin_addr,
+           sizeof(struct in_addr), f->sin_family);
+       if (hp == 0) {
+               dprintf("Host name for your address (%s) unknown\n",
+                       inet_ntoa(f->sin_addr));
+               return (inet_ntoa(f->sin_addr));
+       }
+       if ((p = strchr(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
+               *p = '\0';
+       return (hp->h_name);
+}
+
+void
+domark(signo)
+       int signo;
+{
+       struct filed *f;
+
+       now = time((time_t *)NULL);
+       MarkSeq += TIMERINTVL;
+       if (MarkSeq >= MarkInterval) {
+               logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
+               MarkSeq = 0;
+       }
+
+       for (f = Files; f; f = f->f_next) {
+               if (f->f_prevcount && now >= REPEATTIME(f)) {
+                       dprintf("flush %s: repeated %d times, %d sec.\n",
+                           TypeNames[f->f_type], f->f_prevcount,
+                           repeatinterval[f->f_repeatcount]);
+                       fprintlog(f, 0, (char *)NULL);
+                       BACKOFF(f);
+               }
+       }
+       (void)alarm(TIMERINTVL);
+}
+
+/*
+ * Print syslogd errors some place.
+ */
+void
+logerror(type)
+       char *type;
+{
+       char buf[100];
+
+       if (errno)
+               (void)snprintf(buf,
+                   sizeof(buf), "syslogd: %s: %s", type, strerror(errno));
+       else
+               (void)snprintf(buf, sizeof(buf), "syslogd: %s", type);
+       errno = 0;
+       dprintf("%s\n", buf);
+       logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
+}
+
+void
+die(signo)
+       int signo;
+{
+       struct filed *f;
+       char buf[100];
+
+       for (f = Files; f != NULL; f = f->f_next) {
+               /* flush any pending output */
+               if (f->f_prevcount)
+                       fprintlog(f, 0, (char *)NULL);
+       }
+       if (signo) {
+               dprintf("syslogd: exiting on signal %d\n", signo);
+               (void)snprintf(buf, sizeof buf, "exiting on signal %d", signo);
+               errno = 0;
+               logerror(buf);
+       }
+       (void)unlink(LogName);
+       exit(0);
+}
+
+/*
+ *  INIT -- Initialize syslogd from configuration table
+ */
+void
+init(signo)
+       int signo;
+{
+       int i;
+       FILE *cf;
+       struct filed *f, *next, **nextp;
+       char *p;
+       char cline[LINE_MAX];
+
+       dprintf("init\n");
+
+       /*
+        *  Close all open log files.
+        */
+       Initialized = 0;
+       for (f = Files; f != NULL; f = next) {
+               /* flush any pending output */
+               if (f->f_prevcount)
+                       fprintlog(f, 0, (char *)NULL);
+
+               switch (f->f_type) {
+               case F_FILE:
+               case F_TTY:
+               case F_CONSOLE:
+               case F_FORW:
+                       (void)close(f->f_file);
+                       break;
+               }
+               next = f->f_next;
+               free((char *)f);
+       }
+       Files = NULL;
+       nextp = &Files;
+
+       /* open the configuration file */
+       if ((cf = fopen(ConfFile, "r")) == NULL) {
+               dprintf("cannot open %s\n", ConfFile);
+               *nextp = (struct filed *)calloc(1, sizeof(*f));
+               cfline("*.ERR\t/dev/console", *nextp);
+               (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f));
+               cfline("*.PANIC\t*", (*nextp)->f_next);
+               Initialized = 1;
+               return;
+       }
+
+       /*
+        *  Foreach line in the conf table, open that file.
+        */
+       f = NULL;
+       while (fgets(cline, sizeof(cline), cf) != NULL) {
+               /*
+                * check for end-of-section, comments, strip off trailing
+                * spaces and newline character.
+                */
+               for (p = cline; isspace(*p); ++p)
+                       continue;
+               if (*p == NULL || *p == '#')
+                       continue;
+               for (p = strchr(cline, '\0'); isspace(*--p);)
+                       continue;
+               *++p = '\0';
+               f = (struct filed *)calloc(1, sizeof(*f));
+               *nextp = f;
+               nextp = &f->f_next;
+               cfline(cline, f);
+       }
+
+       /* close the configuration file */
+       (void)fclose(cf);
+
+       Initialized = 1;
+
+       if (Debug) {
+               for (f = Files; f; f = f->f_next) {
+                       for (i = 0; i <= LOG_NFACILITIES; i++)
+                               if (f->f_pmask[i] == INTERNAL_NOPRI)
+                                       printf("X ");
+                               else
+                                       printf("%d ", f->f_pmask[i]);
+                       printf("%s: ", TypeNames[f->f_type]);
+                       switch (f->f_type) {
+                       case F_FILE:
+                       case F_TTY:
+                       case F_CONSOLE:
+                               printf("%s", f->f_un.f_fname);
+                               break;
+
+                       case F_FORW:
+                               printf("%s", f->f_un.f_forw.f_hname);
+                               break;
+
+                       case F_USERS:
+                               for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
+                                       printf("%s, ", f->f_un.f_uname[i]);
+                               break;
+                       }
+                       printf("\n");
+               }
+       }
+
+       logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
+       dprintf("syslogd: restarted\n");
+}
+
+/*
+ * Crack a configuration file line
+ */
+void
+cfline(line, f)
+       char *line;
+       struct filed *f;
+{
+       struct hostent *hp;
+       int i, pri;
+       char *bp, *p, *q;
+       char buf[MAXLINE], ebuf[100];
+
+       dprintf("cfline(%s)\n", line);
+
+       errno = 0;      /* keep strerror() stuff out of logerror messages */
+
+       /* clear out file entry */
+       memset(f, 0, sizeof(*f));
+       for (i = 0; i <= LOG_NFACILITIES; i++)
+               f->f_pmask[i] = INTERNAL_NOPRI;
+
+       /* scan through the list of selectors */
+       for (p = line; *p && *p != '\t';) {
+
+               /* find the end of this facility name list */
+               for (q = p; *q && *q != '\t' && *q++ != '.'; )
+                       continue;
+
+               /* collect priority name */
+               for (bp = buf; *q && !strchr("\t,;", *q); )
+                       *bp++ = *q++;
+               *bp = '\0';
+
+               /* skip cruft */
+               while (strchr(", ;", *q))
+                       q++;
+
+               /* decode priority name */
+               if (*buf == '*')
+                       pri = LOG_PRIMASK + 1;
+               else {
+                       pri = decode(buf, prioritynames);
+                       if (pri < 0) {
+                               (void)snprintf(ebuf, sizeof ebuf, 
+                                   "unknown priority name \"%s\"", buf);
+                               logerror(ebuf);
+                               return;
+                       }
+               }
+
+               /* scan facilities */
+               while (*p && !strchr("\t.;", *p)) {
+                       for (bp = buf; *p && !strchr("\t,;.", *p); )
+                               *bp++ = *p++;
+                       *bp = '\0';
+                       if (*buf == '*')
+                               for (i = 0; i < LOG_NFACILITIES; i++)
+                                       f->f_pmask[i] = pri;
+                       else {
+                               i = decode(buf, facilitynames);
+                               if (i < 0) {
+                                       (void)snprintf(ebuf, sizeof ebuf, 
+                                           "unknown facility name \"%s\"",
+                                           buf);
+                                       logerror(ebuf);
+                                       return;
+                               }
+                               f->f_pmask[i >> 3] = pri;
+                       }
+                       while (*p == ',' || *p == ' ')
+                               p++;
+               }
+
+               p = q;
+       }
+
+       /* skip to action part */
+       while (*p == '\t')
+               p++;
+
+       switch (*p)
+       {
+       case '@':
+               if (!InetInuse)
+                       break;
+               (void)strcpy(f->f_un.f_forw.f_hname, ++p);
+               hp = gethostbyname(p);
+               if (hp == NULL) {
+                       extern int h_errno;
+
+                       logerror(hstrerror(h_errno));
+                       break;
+               }
+               memset(&f->f_un.f_forw.f_addr, 0,
+                        sizeof(f->f_un.f_forw.f_addr));
+               f->f_un.f_forw.f_addr.sin_family = AF_INET;
+               f->f_un.f_forw.f_addr.sin_port = LogPort;
+               memmove(&f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
+               f->f_type = F_FORW;
+               break;
+
+       case '/':
+               (void)strcpy(f->f_un.f_fname, p);
+               if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) {
+                       f->f_file = F_UNUSED;
+                       logerror(p);
+                       break;
+               }
+               if (isatty(f->f_file))
+                       f->f_type = F_TTY;
+               else
+                       f->f_type = F_FILE;
+               if (strcmp(p, ctty) == 0)
+                       f->f_type = F_CONSOLE;
+               break;
+
+       case '*':
+               f->f_type = F_WALL;
+               break;
+
+       default:
+               for (i = 0; i < MAXUNAMES && *p; i++) {
+                       for (q = p; *q && *q != ','; )
+                               q++;
+                       (void)strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE);
+                       if ((q - p) > UT_NAMESIZE)
+                               f->f_un.f_uname[i][UT_NAMESIZE] = '\0';
+                       else
+                               f->f_un.f_uname[i][q - p] = '\0';
+                       while (*q == ',' || *q == ' ')
+                               q++;
+                       p = q;
+               }
+               f->f_type = F_USERS;
+               break;
+       }
+}
+
+
+/*
+ *  Decode a symbolic name to a numeric value
+ */
+int
+decode(name, codetab)
+       const char *name;
+       CODE *codetab;
+{
+       CODE *c;
+       char *p, buf[40];
+
+       if (isdigit(*name))
+               return (atoi(name));
+
+       for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) {
+               if (isupper(*name))
+                       *p = tolower(*name);
+               else
+                       *p = *name;
+       }
+       *p = '\0';
+       for (c = codetab; c->c_name; c++)
+               if (!strcmp(buf, c->c_name))
+                       return (c->c_val);
+
+       return (-1);
+}
diff --git a/talk.tproj/Makefile b/talk.tproj/Makefile
new file mode 100644 (file)
index 0000000..de9a8fa
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = talk
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = talk.h talk_ctl.h
+
+CFILES = ctl.c ctl_transact.c display.c get_addrs.c get_names.c\
+         init_disp.c invite.c io.c look_up.c msgs.c talk.c
+
+OTHERSRCS = Makefile.preamble Makefile talk.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/talk.tproj/Makefile.preamble b/talk.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..925a5c7
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/talk.tproj/PB.project b/talk.tproj/PB.project
new file mode 100644 (file)
index 0000000..f6093c3
--- /dev/null
@@ -0,0 +1,37 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (talk.h, talk_ctl.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (
+            ctl.c, 
+            ctl_transact.c, 
+            display.c, 
+            get_addrs.c, 
+            get_names.c, 
+            init_disp.c, 
+            invite.c, 
+            io.c, 
+            look_up.c, 
+            msgs.c, 
+            talk.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, talk.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = talk; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/talk.tproj/ctl.c b/talk.tproj/ctl.c
new file mode 100644 (file)
index 0000000..d1c016b
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * This file handles haggling with the various talk daemons to
+ * get a socket to talk to. sockt is opened and connected in
+ * the progress
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+#include <netinet/in.h>
+#include "talk.h"
+#include "talk_ctl.h"
+
+struct sockaddr_in daemon_addr = { sizeof(daemon_addr), AF_INET };
+struct sockaddr_in ctl_addr = { sizeof(ctl_addr), AF_INET };
+struct sockaddr_in my_addr = { sizeof(my_addr), AF_INET };
+
+       /* inet addresses of the two machines */
+struct in_addr my_machine_addr;
+struct in_addr his_machine_addr;
+
+u_short daemon_port;   /* port number of the talk daemon */
+
+int    ctl_sockt;
+int    sockt;
+int    invitation_waiting = 0;
+
+CTL_MSG msg;
+
+open_sockt()
+{
+       int length;
+
+       my_addr.sin_addr = my_machine_addr;
+       my_addr.sin_port = 0;
+       sockt = socket(AF_INET, SOCK_STREAM, 0);
+       if (sockt <= 0)
+               p_error("Bad socket");
+       if (bind(sockt, (struct sockaddr *)&my_addr, sizeof(my_addr)) != 0)
+               p_error("Binding local socket");
+       length = sizeof(my_addr);
+       if (getsockname(sockt, (struct sockaddr *)&my_addr, &length) == -1)
+               p_error("Bad address for socket");
+}
+
+/* open the ctl socket */
+open_ctl() 
+{
+       int length;
+
+       ctl_addr.sin_port = 0;
+       ctl_addr.sin_addr = my_machine_addr;
+       ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0);
+       if (ctl_sockt <= 0)
+               p_error("Bad socket");
+       if (bind(ctl_sockt,
+           (struct sockaddr *)&ctl_addr, sizeof(ctl_addr)) != 0)
+               p_error("Couldn't bind to control socket");
+       length = sizeof(ctl_addr);
+       if (getsockname(ctl_sockt,
+           (struct sockaddr *)&ctl_addr, &length) == -1)
+               p_error("Bad address for ctl socket");
+}
+
+/* print_addr is a debug print routine */
+print_addr(addr)
+       struct sockaddr_in addr;
+{
+       int i;
+
+       printf("addr = %x, port = %o, family = %o zero = ",
+               addr.sin_addr, addr.sin_port, addr.sin_family);
+       for (i = 0; i<8;i++)
+       printf("%o ", (int)addr.sin_zero[i]);
+       putchar('\n');
+}
diff --git a/talk.tproj/ctl_transact.c b/talk.tproj/ctl_transact.c
new file mode 100644 (file)
index 0000000..85474dd
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <protocols/talkd.h>
+#include <errno.h>
+#include "talk_ctl.h"
+
+#define CTL_WAIT 2     /* time to wait for a response, in seconds */
+
+/*
+ * SOCKDGRAM is unreliable, so we must repeat messages if we have
+ * not recieved an acknowledgement within a reasonable amount
+ * of time
+ */
+ctl_transact(target, msg, type, rp)
+       struct in_addr target;
+       CTL_MSG msg;
+       int type;
+       CTL_RESPONSE *rp;
+{
+       int read_mask, ctl_mask, nready, cc;
+       struct timeval wait;
+
+       msg.type = type;
+       daemon_addr.sin_addr = target;
+       daemon_addr.sin_port = daemon_port;
+       ctl_mask = 1 << ctl_sockt;
+
+       /*
+        * Keep sending the message until a response of
+        * the proper type is obtained.
+        */
+       do {
+               wait.tv_sec = CTL_WAIT;
+               wait.tv_usec = 0;
+               /* resend message until a response is obtained */
+               do {
+                       cc = sendto(ctl_sockt, (char *)&msg, sizeof (msg), 0,
+                           (struct sockaddr *)&daemon_addr,
+                           sizeof (daemon_addr));
+                       if (cc != sizeof (msg)) {
+                               if (errno == EINTR)
+                                       continue;
+                               p_error("Error on write to talk daemon");
+                       }
+                       read_mask = ctl_mask;
+                       nready = select(32, &read_mask, 0, 0, &wait);
+                       if (nready < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                               p_error("Error waiting for daemon response");
+                       }
+               } while (nready == 0);
+               /*
+                * Keep reading while there are queued messages 
+                * (this is not necessary, it just saves extra
+                * request/acknowledgements being sent)
+                */
+               do {
+                       cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0);
+                       if (cc < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                               p_error("Error on read from talk daemon");
+                       }
+                       read_mask = ctl_mask;
+                       /* an immediate poll */
+                       timerclear(&wait);
+                       nready = select(32, &read_mask, 0, 0, &wait);
+               } while (nready > 0 && (rp->vers != TALK_VERSION ||
+                   rp->type != type));
+       } while (rp->vers != TALK_VERSION || rp->type != type);
+       rp->id_num = ntohl(rp->id_num);
+       rp->addr.sa_family = ntohs(rp->addr.sa_family);
+}
diff --git a/talk.tproj/display.c b/talk.tproj/display.c
new file mode 100644 (file)
index 0000000..6a725a6
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * The window 'manager', initializes curses and handles the actual
+ * displaying of text
+ */
+#include "talk.h"
+
+xwin_t my_win;
+xwin_t his_win;
+WINDOW *line_win;
+
+int    curses_initialized = 0;
+
+/*
+ * max HAS to be a function, it is called with
+ * a argument of the form --foo at least once.
+ */
+max(a,b)
+       int a, b;
+{
+
+       return (a > b ? a : b);
+}
+
+/*
+ * Display some text on somebody's window, processing some control
+ * characters while we are at it.
+ */
+display(win, text, size)
+       register xwin_t *win;
+       register char *text;
+       int size;
+{
+       register int i;
+       char cch;
+
+       for (i = 0; i < size; i++) {
+               if (*text == '\n') {
+                       xscroll(win, 0);
+                       text++;
+                       continue;
+               }
+               /* erase character */
+               if (*text == win->cerase) {
+                       wmove(win->x_win, win->x_line, max(--win->x_col, 0));
+                       getyx(win->x_win, win->x_line, win->x_col);
+                       waddch(win->x_win, ' ');
+                       wmove(win->x_win, win->x_line, win->x_col);
+                       getyx(win->x_win, win->x_line, win->x_col);
+                       text++;
+                       continue;
+               }
+               /*
+                * On word erase search backwards until we find
+                * the beginning of a word or the beginning of
+                * the line.
+                */
+               if (*text == win->werase) {
+                       int endcol, xcol, i, c;
+
+                       endcol = win->x_col;
+                       xcol = endcol - 1;
+                       while (xcol >= 0) {
+                               c = readwin(win->x_win, win->x_line, xcol);
+                               if (c != ' ')
+                                       break;
+                               xcol--;
+                       }
+                       while (xcol >= 0) {
+                               c = readwin(win->x_win, win->x_line, xcol);
+                               if (c == ' ')
+                                       break;
+                               xcol--;
+                       }
+                       wmove(win->x_win, win->x_line, xcol + 1);
+                       for (i = xcol + 1; i < endcol; i++)
+                               waddch(win->x_win, ' ');
+                       wmove(win->x_win, win->x_line, xcol + 1);
+                       getyx(win->x_win, win->x_line, win->x_col);
+                       text++;
+                       continue;
+               }
+               /* line kill */
+               if (*text == win->kill) {
+                       wmove(win->x_win, win->x_line, 0);
+                       wclrtoeol(win->x_win);
+                       getyx(win->x_win, win->x_line, win->x_col);
+                       text++;
+                       continue;
+               }
+               if (*text == '\f') {
+                       if (win == &my_win)
+                               wrefresh(curscr);
+                       text++;
+                       continue;
+               }
+               if (win->x_col == COLS-1) {
+                       /* check for wraparound */
+                       xscroll(win, 0);
+               }
+               if (*text < ' ' && *text != '\t') {
+                       waddch(win->x_win, '^');
+                       getyx(win->x_win, win->x_line, win->x_col);
+                       if (win->x_col == COLS-1) /* check for wraparound */
+                               xscroll(win, 0);
+                       cch = (*text & 63) + 64;
+                       waddch(win->x_win, cch);
+               } else
+                       waddch(win->x_win, *text);
+               getyx(win->x_win, win->x_line, win->x_col);
+               text++;
+       }
+       wrefresh(win->x_win);
+}
+
+/*
+ * Read the character at the indicated position in win
+ */
+readwin(win, line, col)
+       WINDOW *win;
+{
+       int oldline, oldcol;
+       register int c;
+
+       getyx(win, oldline, oldcol);
+       wmove(win, line, col);
+       c = winch(win);
+       wmove(win, oldline, oldcol);
+       return (c);
+}
+
+/*
+ * Scroll a window, blanking out the line following the current line
+ * so that the current position is obvious
+ */
+xscroll(win, flag)
+       register xwin_t *win;
+       int flag;
+{
+
+       if (flag == -1) {
+               wmove(win->x_win, 0, 0);
+               win->x_line = 0;
+               win->x_col = 0;
+               return;
+       }
+       win->x_line = (win->x_line + 1) % win->x_nlines;
+       win->x_col = 0;
+       wmove(win->x_win, win->x_line, win->x_col);
+       wclrtoeol(win->x_win);
+       wmove(win->x_win, (win->x_line + 1) % win->x_nlines, win->x_col);
+       wclrtoeol(win->x_win);
+       wmove(win->x_win, win->x_line, win->x_col);
+}
diff --git a/talk.tproj/get_addrs.c b/talk.tproj/get_addrs.c
new file mode 100644 (file)
index 0000000..ce728c5
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <protocols/talkd.h>
+#include <netdb.h>
+#include <stdio.h>
+#include "talk_ctl.h"
+
+get_addrs(my_machine_name, his_machine_name)
+       char *my_machine_name, *his_machine_name;
+{
+       struct hostent *hp;
+       struct servent *sp;
+
+       msg.pid = htonl(getpid());
+       /* look up the address of the local host */
+       hp = gethostbyname(my_machine_name);
+       if (hp == NULL) {
+               fprintf(stderr, "talk: %s: ", my_machine_name);
+               herror((char *)NULL);
+               exit(-1);
+       }
+       bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
+       /*
+        * If the callee is on-machine, just copy the
+        * network address, otherwise do a lookup...
+        */
+       if (strcmp(his_machine_name, my_machine_name)) {
+               hp = gethostbyname(his_machine_name);
+               if (hp == NULL) {
+                       fprintf(stderr, "talk: %s: ", his_machine_name);
+                       herror((char *)NULL);
+                       exit(-1);
+               }
+               bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
+       } else
+               his_machine_addr = my_machine_addr;
+       /* find the server's port */
+       sp = getservbyname("ntalk", "udp");
+       if (sp == 0) {
+               fprintf(stderr, "talk: %s/%s: service is not registered.\n",
+                    "ntalk", "udp");
+               exit(-1);
+       }
+       daemon_port = sp->s_port;
+}
diff --git a/talk.tproj/get_names.c b/talk.tproj/get_names.c
new file mode 100644 (file)
index 0000000..adf43bc
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+#include <pwd.h>
+#include "talk.h"
+
+char   *getlogin();
+char   *ttyname();
+char   *rindex();
+extern CTL_MSG msg;
+
+/*
+ * Determine the local and remote user, tty, and machines
+ */
+get_names(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char hostname[MAXHOSTNAMELEN];
+       char *his_name, *my_name;
+       char *my_machine_name, *his_machine_name;
+       char *my_tty, *his_tty;
+       register char *cp;
+
+       if (argc < 2 ) {
+               printf("Usage: talk user [ttyname]\n");
+               exit(-1);
+       }
+       if (!isatty(0)) {
+               printf("Standard input must be a tty, not a pipe or a file\n");
+               exit(-1);
+       }
+       if ((my_name = getlogin()) == NULL) {
+               struct passwd *pw;
+
+               if ((pw = getpwuid(getuid())) == NULL) {
+                       printf("You don't exist. Go away.\n");
+                       exit(-1);
+               }
+               my_name = pw->pw_name;
+       }
+       gethostname(hostname, sizeof (hostname));
+       my_machine_name = hostname;
+       /* check for, and strip out, the machine name of the target */
+       for (cp = argv[1]; *cp && !index("@:!.", *cp); cp++)
+               ;
+       if (*cp == '\0') {
+               /* this is a local to local talk */
+               his_name = argv[1];
+               his_machine_name = my_machine_name;
+       } else {
+               if (*cp++ == '@') {
+                       /* user@host */
+                       his_name = argv[1];
+                       his_machine_name = cp;
+               } else {
+                       /* host.user or host!user or host:user */
+                       his_name = cp;
+                       his_machine_name = argv[1];
+               }
+               *--cp = '\0';
+       }
+       if (argc > 2)
+               his_tty = argv[2];      /* tty name is arg 2 */
+       else
+               his_tty = "";
+       get_addrs(my_machine_name, his_machine_name);
+       /*
+        * Initialize the message template.
+        */
+       msg.vers = TALK_VERSION;
+       msg.addr.sa_family = htons(AF_INET);
+       msg.ctl_addr.sa_family = htons(AF_INET);
+       msg.id_num = htonl(0);
+       strncpy(msg.l_name, my_name, NAME_SIZE);
+       msg.l_name[NAME_SIZE - 1] = '\0';
+       strncpy(msg.r_name, his_name, NAME_SIZE);
+       msg.r_name[NAME_SIZE - 1] = '\0';
+       strncpy(msg.r_tty, his_tty, TTY_SIZE);
+       msg.r_tty[TTY_SIZE - 1] = '\0';
+}
diff --git a/talk.tproj/init_disp.c b/talk.tproj/init_disp.c
new file mode 100644 (file)
index 0000000..1332107
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * Initialization code for the display package,
+ * as well as the signal handling routines.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/ioctl_compat.h>
+
+#include <signal.h>
+#include <err.h>
+#include "talk.h"
+
+/* 
+ * Set up curses, catch the appropriate signals,
+ * and build the various windows.
+ */
+init_display()
+{
+       void sig_sent();
+       struct sigvec sigv;
+
+       if (initscr() == NULL)
+               errx(1, "Terminal type unset or lacking necessary features.");
+       (void) sigvec(SIGTSTP, (struct sigvec *)0, &sigv);
+       sigv.sv_mask |= sigmask(SIGALRM);
+       (void) _sigvec_nobind(SIGTSTP, &sigv, (struct sigvec *)0);
+       curses_initialized = 1;
+       clear();
+       refresh();
+       noecho();
+       crmode();
+       signal(SIGINT, sig_sent);
+       signal(SIGPIPE, sig_sent);
+       /* curses takes care of ^Z */
+       my_win.x_nlines = LINES / 2;
+       my_win.x_ncols = COLS;
+       my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0);
+       scrollok(my_win.x_win, FALSE);
+       wclear(my_win.x_win);
+
+       his_win.x_nlines = LINES / 2 - 1;
+       his_win.x_ncols = COLS;
+       his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols,
+           my_win.x_nlines+1, 0);
+       scrollok(his_win.x_win, FALSE);
+       wclear(his_win.x_win);
+
+       line_win = newwin(1, COLS, my_win.x_nlines, 0);
+       box(line_win, '-', '-');
+       wrefresh(line_win);
+       /* let them know we are working on it */
+       current_state = "No connection yet";
+}
+
+/*
+ * Trade edit characters with the other talk. By agreement
+ * the first three characters each talk transmits after
+ * connection are the three edit characters.
+ */
+set_edit_chars()
+{
+       char buf[3];
+       int cc;
+       struct sgttyb tty;
+       struct ltchars ltc;
+       
+       ioctl(0, TIOCGETP, &tty);
+       ioctl(0, TIOCGLTC, (struct sgttyb *)&ltc);
+       my_win.cerase = tty.sg_erase;
+       my_win.kill = tty.sg_kill;
+       if (ltc.t_werasc == (char) -1)
+               my_win.werase = '\027';  /* control W */
+       else
+               my_win.werase = ltc.t_werasc;
+       buf[0] = my_win.cerase;
+       buf[1] = my_win.kill;
+       buf[2] = my_win.werase;
+       cc = write(sockt, buf, sizeof(buf));
+       if (cc != sizeof(buf) )
+               p_error("Lost the connection");
+       cc = read(sockt, buf, sizeof(buf));
+       if (cc != sizeof(buf) )
+               p_error("Lost the connection");
+       his_win.cerase = buf[0];
+       his_win.kill = buf[1];
+       his_win.werase = buf[2];
+}
+
+void
+sig_sent()
+{
+
+       message("Connection closing. Exiting");
+       quit();
+}
+
+/*
+ * All done talking...hang up the phone and reset terminal thingy's
+ */
+quit()
+{
+
+       if (curses_initialized) {
+               wmove(his_win.x_win, his_win.x_nlines-1, 0);
+               wclrtoeol(his_win.x_win);
+               wrefresh(his_win.x_win);
+               endwin();
+       }
+       if (invitation_waiting)
+               send_delete();
+       exit(0);
+}
diff --git a/talk.tproj/invite.c b/talk.tproj/invite.c
new file mode 100644 (file)
index 0000000..47fbf44
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <protocols/talkd.h>
+#include <errno.h>
+#include <setjmp.h>
+#include "talk_ctl.h"
+#include "talk.h"
+
+/*
+ * There wasn't an invitation waiting, so send a request containing
+ * our sockt address to the remote talk daemon so it can invite
+ * him 
+ */
+
+/*
+ * The msg.id's for the invitations
+ * on the local and remote machines.
+ * These are used to delete the 
+ * invitations.
+ */
+int    local_id, remote_id;
+void   re_invite();
+jmp_buf invitebuf;
+
+invite_remote()
+{
+       int nfd, read_mask, template, new_sockt;
+       struct itimerval itimer;
+       CTL_RESPONSE response;
+
+       itimer.it_value.tv_sec = RING_WAIT;
+       itimer.it_value.tv_usec = 0;
+       itimer.it_interval = itimer.it_value;
+       if (listen(sockt, 5) != 0)
+               p_error("Error on attempt to listen for caller");
+#ifdef MSG_EOR
+       /* copy new style sockaddr to old, swap family (short in old) */
+       msg.addr = *(struct osockaddr *)&my_addr;  /* XXX new to old  style*/
+       msg.addr.sa_family = htons(my_addr.sin_family);
+#else
+       msg.addr = *(struct sockaddr *)&my_addr;
+#endif
+       msg.id_num = htonl(-1);         /* an impossible id_num */
+       invitation_waiting = 1;
+       announce_invite();
+       /*
+        * Shut off the automatic messages for a while,
+        * so we can use the interupt timer to resend the invitation
+        */
+       end_msgs();
+       setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
+       message("Waiting for your party to respond");
+       signal(SIGALRM, re_invite);
+       (void) setjmp(invitebuf);
+       while ((new_sockt = accept(sockt, 0, 0)) < 0) {
+               if (errno == EINTR)
+                       continue;
+               p_error("Unable to connect with your party");
+       }
+       close(sockt);
+       sockt = new_sockt;
+
+       /*
+        * Have the daemons delete the invitations now that we
+        * have connected.
+        */
+       current_state = "Waiting for your party to respond";
+       start_msgs();
+
+       msg.id_num = htonl(local_id);
+       ctl_transact(my_machine_addr, msg, DELETE, &response);
+       msg.id_num = htonl(remote_id);
+       ctl_transact(his_machine_addr, msg, DELETE, &response);
+       invitation_waiting = 0;
+}
+
+/*
+ * Routine called on interupt to re-invite the callee
+ */
+void
+re_invite()
+{
+
+       message("Ringing your party again");
+       current_line++;
+       /* force a re-announce */
+       msg.id_num = htonl(remote_id + 1);
+       announce_invite();
+       longjmp(invitebuf, 1);
+}
+
+static char *answers[] = {
+       "answer #0",                                    /* SUCCESS */
+       "Your party is not logged on",                  /* NOT_HERE */
+       "Target machine is too confused to talk to us", /* FAILED */
+       "Target machine does not recognize us",         /* MACHINE_UNKNOWN */
+       "Your party is refusing messages",              /* PERMISSION_REFUSED */
+       "Target machine can not handle remote talk",    /* UNKNOWN_REQUEST */
+       "Target machine indicates protocol mismatch",   /* BADVERSION */
+       "Target machine indicates protocol botch (addr)",/* BADADDR */
+       "Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */
+};
+#define        NANSWERS        (sizeof (answers) / sizeof (answers[0]))
+
+/*
+ * Transmit the invitation and process the response
+ */
+announce_invite()
+{
+       CTL_RESPONSE response;
+
+       current_state = "Trying to connect to your party's talk daemon";
+       ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
+       remote_id = response.id_num;
+       if (response.answer != SUCCESS) {
+               if (response.answer < NANSWERS)
+                       message(answers[response.answer]);
+               quit();
+       }
+       /* leave the actual invitation on my talk daemon */
+       ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
+       local_id = response.id_num;
+}
+
+/*
+ * Tell the daemon to remove your invitation
+ */
+send_delete()
+{
+
+       msg.type = DELETE;
+       /*
+        * This is just a extra clean up, so just send it
+        * and don't wait for an answer
+        */
+       msg.id_num = htonl(remote_id);
+       daemon_addr.sin_addr = his_machine_addr;
+       if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
+           (struct sockaddr *)&daemon_addr,
+           sizeof (daemon_addr)) != sizeof(msg))
+               perror("send_delete (remote)");
+       msg.id_num = htonl(local_id);
+       daemon_addr.sin_addr = my_machine_addr;
+       if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
+           (struct sockaddr *)&daemon_addr,
+           sizeof (daemon_addr)) != sizeof (msg))
+               perror("send_delete (local)");
+}
diff --git a/talk.tproj/io.c b/talk.tproj/io.c
new file mode 100644 (file)
index 0000000..efd3c30
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * This file contains the I/O handling and the exchange of 
+ * edit characters. This connection itself is established in
+ * ctl.c
+ */
+
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "talk.h"
+
+#define A_LONG_TIME 10000000
+#define STDIN_MASK (1<<fileno(stdin))  /* the bit mask for standard
+                                          input */
+
+/*
+ * The routine to do the actual talking
+ */
+talk()
+{
+       register int read_template, sockt_mask;
+       int read_set, nb;
+       char buf[BUFSIZ];
+       struct timeval wait;
+
+       message("Connection established\007\007\007");
+       current_line = 0;
+       sockt_mask = (1<<sockt);
+
+       /*
+        * Wait on both the other process (sockt_mask) and 
+        * standard input ( STDIN_MASK )
+        */
+       read_template = sockt_mask | STDIN_MASK;
+       for (;;) {
+               read_set = read_template;
+               wait.tv_sec = A_LONG_TIME;
+               wait.tv_usec = 0;
+               nb = select(32, &read_set, 0, 0, &wait);
+               if (nb <= 0) {
+                       if (errno == EINTR) {
+                               read_set = read_template;
+                               continue;
+                       }
+                       /* panic, we don't know what happened */
+                       p_error("Unexpected error from select");
+                       quit();
+               }
+               if (read_set & sockt_mask) { 
+                       /* There is data on sockt */
+                       nb = read(sockt, buf, sizeof buf);
+                       if (nb <= 0) {
+                               message("Connection closed. Exiting");
+                               quit();
+                       }
+                       display(&his_win, buf, nb);
+               }
+               if (read_set & STDIN_MASK) {
+                       /*
+                        * We can't make the tty non_blocking, because
+                        * curses's output routines would screw up
+                        */
+                       ioctl(0, FIONREAD, (struct sgttyb *) &nb);
+                       nb = read(0, buf, nb);
+                       display(&my_win, buf, nb);
+                       /* might lose data here because sockt is non-blocking */
+                       write(sockt, buf, nb);
+               }
+       }
+}
+
+extern int errno;
+extern int sys_nerr;
+
+/*
+ * p_error prints the system error message on the standard location
+ * on the screen and then exits. (i.e. a curses version of perror)
+ */
+p_error(string) 
+       char *string;
+{
+       wmove(my_win.x_win, current_line%my_win.x_nlines, 0);
+       wprintw(my_win.x_win, "[%s : %s (%d)]\n",
+           string, strerror(errno), errno);
+       wrefresh(my_win.x_win);
+       move(LINES-1, 0);
+       refresh();
+       quit();
+}
+
+/*
+ * Display string in the standard location
+ */
+message(string)
+       char *string;
+{
+       wmove(my_win.x_win, current_line % my_win.x_nlines, 0);
+       wprintw(my_win.x_win, "[%s]", string);
+       wclrtoeol(my_win.x_win);
+       current_line++;
+       wmove(my_win.x_win, current_line % my_win.x_nlines, 0);
+       wrefresh(my_win.x_win);
+}
diff --git a/talk.tproj/look_up.c b/talk.tproj/look_up.c
new file mode 100644 (file)
index 0000000..3d46cb3
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <protocols/talkd.h>
+#include <errno.h>
+#include "talk_ctl.h"
+#include "talk.h"
+
+/*
+ * See if the local daemon has an invitation for us.
+ */
+check_local()
+{
+       CTL_RESPONSE response;
+       register CTL_RESPONSE *rp = &response;
+
+       /* the rest of msg was set up in get_names */
+#ifdef MSG_EOR
+       /* copy new style sockaddr to old, swap family (short in old) */
+       msg.ctl_addr = *(struct osockaddr *)&ctl_addr;
+       msg.ctl_addr.sa_family = htons(ctl_addr.sin_family);
+#else
+       msg.ctl_addr = *(struct sockaddr *)&ctl_addr;
+#endif
+       /* must be initiating a talk */
+       if (!look_for_invite(rp))
+               return (0);
+       /*
+        * There was an invitation waiting for us, 
+        * so connect with the other (hopefully waiting) party 
+        */
+       current_state = "Waiting to connect with caller";
+       do {
+               if (rp->addr.sa_family != AF_INET)
+                       p_error("Response uses invalid network address");
+               errno = 0;
+               if (connect(sockt,
+                   (struct sockaddr *)&rp->addr, sizeof (rp->addr)) != -1)
+                       return (1);
+       } while (errno == EINTR);
+       if (errno == ECONNREFUSED) {
+               /*
+                * The caller gave up, but his invitation somehow
+                * was not cleared. Clear it and initiate an 
+                * invitation. (We know there are no newer invitations,
+                * the talkd works LIFO.)
+                */
+               ctl_transact(his_machine_addr, msg, DELETE, rp);
+               close(sockt);
+               open_sockt();
+               return (0);
+       }
+       p_error("Unable to connect with initiator");
+       /*NOTREACHED*/
+}
+
+/*
+ * Look for an invitation on 'machine'
+ */
+look_for_invite(rp)
+       CTL_RESPONSE *rp;
+{
+       struct in_addr machine_addr;
+
+       current_state = "Checking for invitation on caller's machine";
+       ctl_transact(his_machine_addr, msg, LOOK_UP, rp);
+       /* the switch is for later options, such as multiple invitations */
+       switch (rp->answer) {
+
+       case SUCCESS:
+               msg.id_num = htonl(rp->id_num);
+               return (1);
+
+       default:
+               /* there wasn't an invitation waiting for us */
+               return (0);
+       }
+}
diff --git a/talk.tproj/msgs.c b/talk.tproj/msgs.c
new file mode 100644 (file)
index 0000000..7e1edb1
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/* 
+ * A package to display what is happening every MSG_INTERVAL seconds
+ * if we are slow connecting.
+ */
+
+#include <sys/time.h>
+#include <signal.h>
+#include <stdio.h>
+#include "talk.h"
+
+#define MSG_INTERVAL 4
+
+char   *current_state;
+int    current_line = 0;
+
+void
+disp_msg()
+{
+       message(current_state);
+}
+
+start_msgs()
+{
+       struct itimerval itimer;
+
+       message(current_state);
+       signal(SIGALRM, disp_msg);
+       itimer.it_value.tv_sec = itimer.it_interval.tv_sec = MSG_INTERVAL;
+       itimer.it_value.tv_usec = itimer.it_interval.tv_usec = 0;
+       setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
+}
+
+end_msgs()
+{
+       struct itimerval itimer;
+
+       timerclear(&itimer.it_value);
+       timerclear(&itimer.it_interval);
+       setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
+       signal(SIGALRM, SIG_DFL);
+}
diff --git a/talk.tproj/talk.1 b/talk.tproj/talk.1
new file mode 100644 (file)
index 0000000..18c3304
--- /dev/null
@@ -0,0 +1,129 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)talk.1     8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt TALK 1
+.Os BSD 4.2
+.Sh NAME
+.Nm talk
+.Nd talk to another user
+.Sh SYNOPSIS
+.Nm talk
+.Ar person
+.Op Ar ttyname
+.Sh DESCRIPTION
+.Nm Talk
+is a visual communication program which copies lines from your
+terminal to that of another user.
+.Pp
+Options available:
+.Bl -tag -width ttyname
+.It Ar person
+If you wish to talk to someone on your own machine, then
+.Ar person
+is just the person's login name.  If you wish to talk to a user on
+another host, then
+.Ar person
+is of the form
+.Ql user@host .
+.It Ar ttyname
+If you wish to talk to a user who is logged in more than once, the
+.Ar ttyname
+argument may be used to indicate the appropriate terminal
+name, where
+.Ar ttyname
+is of the form
+.Ql ttyXX .
+.El
+.Pp
+When first called,
+.Nm talk
+sends the message
+.Bd -literal -offset indent -compact
+Message from TalkDaemon@his_machine...
+talk: connection requested by your_name@your_machine.
+talk: respond with: talk your_name@your_machine
+.Ed
+.Pp
+to the user you wish to talk to. At this point, the recipient
+of the message should reply by typing
+.Pp
+.Dl talk \ your_name@your_machine
+.Pp
+It doesn't matter from which machine the recipient replies, as
+long as his login-name is the same.  Once communication is established,
+the two parties may type simultaneously, with their output appearing
+in separate windows.  Typing control-L
+.Ql ^L
+will cause the screen to
+be reprinted, while your erase, kill, and word kill characters will
+behave normally.  To exit, just type your interrupt character;
+.Nm talk
+then moves the cursor to the bottom of the screen and restores the
+terminal to its previous state.
+.Pp
+Permission to talk may be denied or granted by use of the
+.Xr mesg 1
+command.  At the outset talking is allowed.  Certain commands, in
+particular
+.Xr nroff 1
+and
+.Xr pr 1 ,
+disallow messages in order to
+prevent messy output.
+.Pp
+.Sh FILES
+.Bl -tag -width /var/run/utmp -compact
+.It Pa /etc/hosts
+to find the recipient's machine
+.It Pa /var/run/utmp
+to find the recipient's tty
+.El
+.Sh SEE ALSO
+.Xr mail 1 ,
+.Xr mesg 1 ,
+.Xr who 1 ,
+.Xr write 1
+.Sh BUGS
+The version of
+.Xr talk 1
+released with
+.Bx 4.3
+uses a protocol that
+is incompatible with the protocol used in the version released with
+.Bx 4.2 .
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/talk.tproj/talk.c b/talk.tproj/talk.c
new file mode 100644 (file)
index 0000000..3690d01
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "talk.h"
+
+/*
+ * talk:       A visual form of write. Using sockets, a two way 
+ *             connection is set up between the two people talking. 
+ *             With the aid of curses, the screen is split into two 
+ *             windows, and each users text is added to the window,
+ *             one character at a time...
+ *
+ *             Written by Kipp Hickman
+ *             
+ *             Modified to run under 4.1a by Clem Cole and Peter Moore
+ *             Modified to run between hosts by Peter Moore, 8/19/82
+ *             Modified to run under 4.1c by Peter Moore 3/17/83
+ */
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       get_names(argc, argv);
+       init_display();
+       open_ctl();
+       open_sockt();
+       start_msgs();
+       if (!check_local())
+               invite_remote();
+       end_msgs();
+       set_edit_chars();
+       talk();
+}
diff --git a/talk.tproj/talk.h b/talk.tproj/talk.h
new file mode 100644 (file)
index 0000000..2458247
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)talk.h      8.1 (Berkeley) 6/6/93
+ */
+
+#include <curses.h>
+
+extern int sockt;
+extern int curses_initialized;
+extern int invitation_waiting;
+
+extern char *current_state;
+extern int current_line;
+
+typedef struct xwin {
+       WINDOW  *x_win;
+       int     x_nlines;
+       int     x_ncols;
+       int     x_line;
+       int     x_col;
+       char    kill;
+       char    cerase;
+       char    werase;
+} xwin_t;
+
+extern xwin_t my_win;
+extern xwin_t his_win;
+extern WINDOW *line_win;
diff --git a/talk.tproj/talk_ctl.h b/talk.tproj/talk_ctl.h
new file mode 100644 (file)
index 0000000..bfe8416
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)talk_ctl.h  8.1 (Berkeley) 6/6/93
+ */
+
+extern struct sockaddr_in daemon_addr;
+extern struct sockaddr_in ctl_addr;
+extern struct sockaddr_in my_addr;
+extern struct in_addr my_machine_addr;
+extern struct in_addr his_machine_addr;
+extern u_short daemon_port;
+extern int ctl_sockt;
+extern CTL_MSG msg;
diff --git a/talkd.tproj/Makefile b/talkd.tproj/Makefile
new file mode 100644 (file)
index 0000000..e727fa6
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ntalkd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = talkd.h
+
+CFILES = announce.c print.c process.c table.c talkd.c
+
+OTHERSRCS = Makefile Makefile.dist Makefile.postamble Makefile.preamble\
+            talkd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/talkd.tproj/Makefile.dist b/talkd.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..51f6806
--- /dev/null
@@ -0,0 +1,8 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/4/93
+
+PROG=  ntalkd
+SRCS=  talkd.c announce.c process.c table.c print.c ttymsg.c
+.PATH:  ${.CURDIR}/../../usr.bin/wall
+MAN8=  talkd.0
+
+.include <bsd.prog.mk>
diff --git a/talkd.tproj/Makefile.postamble b/talkd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..9d4f92c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
+VPATH += :../wall.tproj
+
diff --git a/talkd.tproj/Makefile.preamble b/talkd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..9764639
--- /dev/null
@@ -0,0 +1,120 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES= ttymsg.o
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+OTHER_OFILES = ttymsg.o
+-include ../Makefile.include
diff --git a/talkd.tproj/PB.project b/talkd.tproj/PB.project
new file mode 100644 (file)
index 0000000..15be3ec
--- /dev/null
@@ -0,0 +1,39 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (talkd.h); 
+        M_FILES = (); 
+        OTHER_LINKED = (announce.c, print.c, process.c, table.c, talkd.c); 
+        OTHER_SOURCES = (Makefile, Makefile.dist, Makefile.postamble, Makefile.preamble, talkd.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ntalkd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/talkd.tproj/announce.c b/talkd.tproj/announce.c
new file mode 100644 (file)
index 0000000..cda84a1
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)announce.c 8.3 (Berkeley) 1/7/94";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+#include <sgtty.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <vis.h>
+#include "talkd.h"
+
+extern char hostname[];
+
+int print_mesg __P((char *tty, CTL_MSG *request, char *remote_machine));
+
+/*
+ * Announce an invitation to talk.
+ */
+       
+/*
+ * See if the user is accepting messages. If so, announce that 
+ * a talk is requested.
+ */
+int
+announce(request, remote_machine)
+       CTL_MSG *request;
+       char *remote_machine;
+{
+       char full_tty[32];
+       struct stat stbuf;
+
+       (void)snprintf(full_tty, sizeof(full_tty),
+           "%s%s", _PATH_DEV, request->r_tty);
+       if (stat(full_tty, &stbuf) < 0 || (stbuf.st_mode&020) == 0)
+               return (PERMISSION_DENIED);
+       return (print_mesg(request->r_tty, request, remote_machine));
+}
+
+#define max(a,b) ( (a) > (b) ? (a) : (b) )
+#define N_LINES 5
+#define N_CHARS 256
+
+/*
+ * Build a block of characters containing the message. 
+ * It is sent blank filled and in a single block to
+ * try to keep the message in one piece if the recipient
+ * in in vi at the time
+ */
+int
+print_mesg(tty, request, remote_machine)
+       char *tty;
+       CTL_MSG *request;
+       char *remote_machine;
+{
+       struct timeval clock;
+       struct timezone zone;
+       struct tm *localtime();
+       struct tm *localclock;
+       struct iovec iovec;
+       char line_buf[N_LINES][N_CHARS];
+       int sizes[N_LINES];
+       char big_buf[N_LINES*N_CHARS];
+       char *bptr, *lptr, *vis_user;
+       int i, j, max_size;
+
+       i = 0;
+       max_size = 0;
+       gettimeofday(&clock, &zone);
+       localclock = localtime( &clock.tv_sec );
+       (void)snprintf(line_buf[i], N_CHARS, " ");
+       sizes[i] = strlen(line_buf[i]);
+       max_size = max(max_size, sizes[i]);
+       i++;
+       (void)snprintf(line_buf[i], N_CHARS,
+               "Message from Talk_Daemon@%s at %d:%02d ...",
+               hostname, localclock->tm_hour , localclock->tm_min );
+       sizes[i] = strlen(line_buf[i]);
+       max_size = max(max_size, sizes[i]);
+       i++;
+
+       vis_user = malloc(strlen(request->l_name) * 4 + 1);
+       strvis(vis_user, request->l_name, VIS_CSTYLE);
+       (void)snprintf(line_buf[i], N_CHARS,
+       "talk: connection requested by %s@%s", vis_user, remote_machine);
+       sizes[i] = strlen(line_buf[i]);
+       max_size = max(max_size, sizes[i]);
+       i++;
+       (void)snprintf(line_buf[i], N_CHARS, "talk: respond with:  talk %s@%s",
+       vis_user, remote_machine);
+       sizes[i] = strlen(line_buf[i]);
+       max_size = max(max_size, sizes[i]);
+       i++;
+       (void)snprintf(line_buf[i], N_CHARS, " ");
+       sizes[i] = strlen(line_buf[i]);
+       max_size = max(max_size, sizes[i]);
+       i++;
+       bptr = big_buf;
+       *bptr++ = '\a'; /* send something to wake them up */
+       *bptr++ = '\r'; /* add a \r in case of raw mode */
+       *bptr++ = '\n';
+       for (i = 0; i < N_LINES; i++) {
+               /* copy the line into the big buffer */
+               lptr = line_buf[i];
+               while (*lptr != '\0')
+                       *(bptr++) = *(lptr++);
+               /* pad out the rest of the lines with blanks */
+               for (j = sizes[i]; j < max_size + 2; j++)
+                       *(bptr++) = ' ';
+               *(bptr++) = '\r';       /* add a \r in case of raw mode */
+               *(bptr++) = '\n';
+       }
+       *bptr = '\0';
+       iovec.iov_base = big_buf;
+       iovec.iov_len = bptr - big_buf;
+       /*
+        * we choose a timeout of RING_WAIT-5 seconds so that we don't
+        * stack up processes trying to write messages to a tty
+        * that is permanently blocked.
+        */
+       if (ttymsg(&iovec, 1, tty, RING_WAIT - 5) != NULL)
+               return (FAILED);
+
+       return (SUCCESS);
+}
diff --git a/talkd.tproj/print.c b/talkd.tproj/print.c
new file mode 100644 (file)
index 0000000..74f7aa8
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)print.c    8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* debug print routines */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+#include <syslog.h>
+#include <stdio.h>
+
+static char *types[] =
+    { "leave_invite", "look_up", "delete", "announce" };
+#define        NTYPES  (sizeof (types) / sizeof (types[0]))
+static char *answers[] = 
+    { "success", "not_here", "failed", "machine_unknown", "permission_denied",
+      "unknown_request", "badversion", "badaddr", "badctladdr" };
+#define        NANSWERS        (sizeof (answers) / sizeof (answers[0]))
+
+void
+print_request(cp, mp)
+       char *cp;
+       register CTL_MSG *mp;
+{
+       char tbuf[80], *tp;
+       
+       if (mp->type > NTYPES) {
+               (void)sprintf(tbuf, "type %d", mp->type);
+               tp = tbuf;
+       } else
+               tp = types[mp->type];
+       syslog(LOG_DEBUG, "%s: %s: id %d, l_user %s, r_user %s, r_tty %s",
+           cp, tp, mp->id_num, mp->l_name, mp->r_name, mp->r_tty);
+}
+
+void
+print_response(cp, rp)
+       char *cp;
+       register CTL_RESPONSE *rp;
+{
+       char tbuf[80], *tp, abuf[80], *ap;
+       
+       if (rp->type > NTYPES) {
+               (void)sprintf(tbuf, "type %d", rp->type);
+               tp = tbuf;
+       } else
+               tp = types[rp->type];
+       if (rp->answer > NANSWERS) {
+               (void)sprintf(abuf, "answer %d", rp->answer);
+               ap = abuf;
+       } else
+               ap = answers[rp->answer];
+       syslog(LOG_DEBUG, "%s: %s: %s, id %d", cp, tp, ap, ntohl(rp->id_num));
+}
diff --git a/talkd.tproj/process.c b/talkd.tproj/process.c
new file mode 100644 (file)
index 0000000..c7d7b2c
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)process.c  8.2 (Berkeley) 11/16/93";
+#endif /* not lint */
+
+/*
+ * process.c handles the requests, which can be of three types:
+ *     ANNOUNCE - announce to a user that a talk is wanted
+ *     LEAVE_INVITE - insert the request into the table
+ *     LOOK_UP - look up to see if a request is waiting in
+ *               in the table for the local user
+ *     DELETE - delete invitation
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <protocols/talkd.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <string.h>
+#include <paths.h>
+#include "talkd.h"
+
+CTL_MSG *find_request();
+CTL_MSG *find_match();
+
+void
+process_request(mp, rp)
+       register CTL_MSG *mp;
+       register CTL_RESPONSE *rp;
+{
+       register CTL_MSG *ptr;
+       extern int debug;
+
+       rp->vers = TALK_VERSION;
+       rp->type = mp->type;
+       rp->id_num = htonl(0);
+       if (mp->vers != TALK_VERSION) {
+               syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
+               rp->answer = BADVERSION;
+               return;
+       }
+       mp->id_num = ntohl(mp->id_num);
+       mp->addr.sa_family = ntohs(mp->addr.sa_family);
+       if (mp->addr.sa_family != AF_INET) {
+               syslog(LOG_WARNING, "Bad address, family %d",
+                   mp->addr.sa_family);
+               rp->answer = BADADDR;
+               return;
+       }
+       mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
+       if (mp->ctl_addr.sa_family != AF_INET) {
+               syslog(LOG_WARNING, "Bad control address, family %d",
+                   mp->ctl_addr.sa_family);
+               rp->answer = BADCTLADDR;
+               return;
+       }
+       mp->pid = ntohl(mp->pid);
+       if (debug)
+               print_request("process_request", mp);
+       switch (mp->type) {
+
+       case ANNOUNCE:
+               do_announce(mp, rp);
+               break;
+
+       case LEAVE_INVITE:
+               ptr = find_request(mp);
+               if (ptr != (CTL_MSG *)0) {
+                       rp->id_num = htonl(ptr->id_num);
+                       rp->answer = SUCCESS;
+               } else
+                       insert_table(mp, rp);
+               break;
+
+       case LOOK_UP:
+               ptr = find_match(mp);
+               if (ptr != (CTL_MSG *)0) {
+                       rp->id_num = htonl(ptr->id_num);
+                       rp->addr = ptr->addr;
+                       rp->addr.sa_family = htons(ptr->addr.sa_family);
+                       rp->answer = SUCCESS;
+               } else
+                       rp->answer = NOT_HERE;
+               break;
+
+       case DELETE:
+               rp->answer = delete_invite(mp->id_num);
+               break;
+
+       default:
+               rp->answer = UNKNOWN_REQUEST;
+               break;
+       }
+       if (debug)
+               print_response("process_request", rp);
+}
+
+void
+do_announce(mp, rp)
+       register CTL_MSG *mp;
+       CTL_RESPONSE *rp;
+{
+       struct hostent *hp;
+       CTL_MSG *ptr;
+       int result;
+
+       /* see if the user is logged */
+       result = find_user(mp->r_name, mp->r_tty);
+       if (result != SUCCESS) {
+               rp->answer = result;
+               return;
+       }
+#define        satosin(sa)     ((struct sockaddr_in *)(sa))
+       hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr,
+               sizeof (struct in_addr), AF_INET);
+       if (hp == (struct hostent *)0) {
+               rp->answer = MACHINE_UNKNOWN;
+               return;
+       }
+       ptr = find_request(mp);
+       if (ptr == (CTL_MSG *) 0) {
+               insert_table(mp, rp);
+               rp->answer = announce(mp, hp->h_name);
+               return;
+       }
+       if (mp->id_num > ptr->id_num) {
+               /*
+                * This is an explicit re-announce, so update the id_num
+                * field to avoid duplicates and re-announce the talk.
+                */
+               ptr->id_num = new_id();
+               rp->id_num = htonl(ptr->id_num);
+               rp->answer = announce(mp, hp->h_name);
+       } else {
+               /* a duplicated request, so ignore it */
+               rp->id_num = htonl(ptr->id_num);
+               rp->answer = SUCCESS;
+       }
+}
+
+#include <utmp.h>
+
+/*
+ * Search utmp for the local user
+ */
+int
+find_user(name, tty)
+       char *name, *tty;
+{
+       struct utmp ubuf;
+       int status;
+       FILE *fd;
+       struct stat statb;
+       char line[sizeof(ubuf.ut_line) + 1];
+       char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)];
+
+       if ((fd = fopen(_PATH_UTMP, "r")) == NULL) {
+               fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
+               return (FAILED);
+       }
+#define SCMPN(a, b)    strncmp(a, b, sizeof (a))
+       status = NOT_HERE;
+       (void) strcpy(ftty, _PATH_DEV);
+       while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
+               if (SCMPN(ubuf.ut_name, name) == 0) {
+                       strncpy(line, ubuf.ut_line, sizeof(ubuf.ut_line));
+                       line[sizeof(ubuf.ut_line)] = '\0';
+                       if (*tty == '\0') {
+                               status = PERMISSION_DENIED;
+                               /* no particular tty was requested */
+                               (void) strcpy(ftty + sizeof(_PATH_DEV) - 1,
+                                   line);
+                               if (stat(ftty, &statb) == 0) {
+                                       if (!(statb.st_mode & 020))
+                                               continue;
+                                       (void) strcpy(tty, line);
+                                       status = SUCCESS;
+                                       break;
+                               }
+                       }
+                       if (strcmp(line, tty) == 0) {
+                               status = SUCCESS;
+                               break;
+                       }
+               }
+       fclose(fd);
+       return (status);
+}
diff --git a/talkd.tproj/table.c b/talkd.tproj/table.c
new file mode 100644 (file)
index 0000000..df3fb23
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)table.c    8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * Routines to handle insertion, deletion, etc on the table
+ * of requests kept by the daemon. Nothing fancy here, linear
+ * search on a double-linked list. A time is kept with each 
+ * entry so that overly old invitations can be eliminated.
+ *
+ * Consider this a mis-guided attempt at modularity
+ */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "talkd.h"
+
+#define MAX_ID 16000   /* << 2^15 so I don't have sign troubles */
+
+#define NIL ((TABLE_ENTRY *)0)
+
+extern int debug;
+struct timeval tp;
+struct timezone txp;
+
+typedef struct table_entry TABLE_ENTRY;
+
+struct table_entry {
+       CTL_MSG request;
+       long    time;
+       TABLE_ENTRY *next;
+       TABLE_ENTRY *last;
+};
+
+TABLE_ENTRY *table = NIL;
+CTL_MSG *find_request();
+CTL_MSG *find_match();
+
+void   delete __P((TABLE_ENTRY *ptr));
+
+/*
+ * Look in the table for an invitation that matches the current
+ * request looking for an invitation
+ */
+CTL_MSG *
+find_match(request)
+       register CTL_MSG *request;
+{
+       register TABLE_ENTRY *ptr;
+       time_t current_time;
+
+       gettimeofday(&tp, &txp);
+       current_time = tp.tv_sec;
+       if (debug)
+               print_request("find_match", request);
+       for (ptr = table; ptr != NIL; ptr = ptr->next) {
+               if ((ptr->time - current_time) > MAX_LIFE) {
+                       /* the entry is too old */
+                       if (debug)
+                               print_request("deleting expired entry",
+                                   &ptr->request);
+                       delete(ptr);
+                       continue;
+               }
+               if (debug)
+                       print_request("", &ptr->request);
+               if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
+                   strcmp(request->r_name, ptr->request.l_name) == 0 &&
+                    ptr->request.type == LEAVE_INVITE)
+                       return (&ptr->request);
+       }
+       return ((CTL_MSG *)0);
+}
+
+/*
+ * Look for an identical request, as opposed to a complimentary
+ * one as find_match does 
+ */
+CTL_MSG *
+find_request(request)
+       register CTL_MSG *request;
+{
+       register TABLE_ENTRY *ptr;
+       time_t current_time;
+
+       gettimeofday(&tp, &txp);
+       current_time = tp.tv_sec;
+       /*
+        * See if this is a repeated message, and check for
+        * out of date entries in the table while we are it.
+        */
+       if (debug)
+               print_request("find_request", request);
+       for (ptr = table; ptr != NIL; ptr = ptr->next) {
+               if ((ptr->time - current_time) > MAX_LIFE) {
+                       /* the entry is too old */
+                       if (debug)
+                               print_request("deleting expired entry",
+                                   &ptr->request);
+                       delete(ptr);
+                       continue;
+               }
+               if (debug)
+                       print_request("", &ptr->request);
+               if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
+                   strcmp(request->l_name, ptr->request.l_name) == 0 &&
+                   request->type == ptr->request.type &&
+                   request->pid == ptr->request.pid) {
+                       /* update the time if we 'touch' it */
+                       ptr->time = current_time;
+                       return (&ptr->request);
+               }
+       }
+       return ((CTL_MSG *)0);
+}
+
+void
+insert_table(request, response)
+       CTL_MSG *request;
+       CTL_RESPONSE *response;
+{
+       register TABLE_ENTRY *ptr;
+       time_t current_time;
+
+       gettimeofday(&tp, &txp);
+       current_time = tp.tv_sec;
+       request->id_num = new_id();
+       response->id_num = htonl(request->id_num);
+       /* insert a new entry into the top of the list */
+       ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
+       if (ptr == NIL) {
+               syslog(LOG_ERR, "insert_table: Out of memory");
+               _exit(1);
+       }
+       ptr->time = current_time;
+       ptr->request = *request;
+       ptr->next = table;
+       if (ptr->next != NIL)
+               ptr->next->last = ptr;
+       ptr->last = NIL;
+       table = ptr;
+}
+
+/*
+ * Generate a unique non-zero sequence number
+ */
+int
+new_id()
+{
+       static int current_id = 0;
+
+       current_id = (current_id + 1) % MAX_ID;
+       /* 0 is reserved, helps to pick up bugs */
+       if (current_id == 0)
+               current_id = 1;
+       return (current_id);
+}
+
+/*
+ * Delete the invitation with id 'id_num'
+ */
+int
+delete_invite(id_num)
+       int id_num;
+{
+       register TABLE_ENTRY *ptr;
+
+       ptr = table;
+       if (debug)
+               syslog(LOG_DEBUG, "delete_invite(%d)", id_num);
+       for (ptr = table; ptr != NIL; ptr = ptr->next) {
+               if (ptr->request.id_num == id_num)
+                       break;
+               if (debug)
+                       print_request("", &ptr->request);
+       }
+       if (ptr != NIL) {
+               delete(ptr);
+               return (SUCCESS);
+       }
+       return (NOT_HERE);
+}
+
+/*
+ * Classic delete from a double-linked list
+ */
+void
+delete(ptr)
+       register TABLE_ENTRY *ptr;
+{
+
+       if (debug)
+               print_request("delete", &ptr->request);
+       if (table == ptr)
+               table = ptr->next;
+       else if (ptr->last != NIL)
+               ptr->last->next = ptr->next;
+       if (ptr->next != NIL)
+               ptr->next->last = ptr->last;
+       free((char *)ptr);
+}
diff --git a/talkd.tproj/talkd.8 b/talkd.tproj/talkd.8
new file mode 100644 (file)
index 0000000..36dfb28
--- /dev/null
@@ -0,0 +1,75 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)talkd.8    8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt TALKD 8
+.Os BSD 4.3
+.Sh NAME
+.Nm talkd
+.Nd remote user communication server
+.Sh SYNOPSIS
+.Nm talkd
+.Sh DESCRIPTION
+.Nm Talkd
+is the server that notifies a user that someone else wants to
+initiate a conversation.
+It acts as a repository of invitations, responding to requests
+by clients wishing to rendezvous to hold a conversation.
+In normal operation, a client, the caller,
+initiates a rendezvous by sending a
+.Tn CTL_MSG
+to the server of
+type
+.Tn LOOK_UP
+(see
+.Aq Pa protocols/talkd.h ) .
+This causes the server to search its invitation
+tables to check if an invitation currently exists for the caller
+(to speak to the callee specified in the message).
+If the lookup fails,
+the caller then sends an
+.Tn ANNOUNCE
+message causing the server to
+broadcast an announcement on the callee's login ports requesting contact.
+When the callee responds, the local server uses the
+recorded invitation to respond with the appropriate rendezvous
+address and the caller and callee client programs establish a
+stream connection through which the conversation takes place.
+.Sh SEE ALSO
+.Xr talk 1 ,
+.Xr write 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/talkd.tproj/talkd.c b/talkd.tproj/talkd.c
new file mode 100644 (file)
index 0000000..7281351
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)talkd.c    8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * The top level of the daemon, the format is heavily borrowed
+ * from rwhod.c. Basically: find out who and where you are; 
+ * disconnect all descriptors and ttys, and then endless
+ * loop on waiting for and processing requests
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+#include <signal.h>
+#include <syslog.h>
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <sys/param.h>
+#include "talkd.h"
+
+CTL_MSG                request;
+CTL_RESPONSE   response;
+
+int    sockt;
+int    debug = 0;
+void   timeout();
+long   lastmsgtime;
+
+char   hostname[MAXHOSTNAMELEN + 1];
+
+#define TIMEOUT 30
+#define MAXIDLE 120
+
+void
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register CTL_MSG *mp = &request;
+       int cc;
+
+       if (getuid()) {
+               fprintf(stderr, "%s: getuid: not super-user\n", argv[0]);
+               exit(1);
+       }
+       openlog("talkd", LOG_PID, LOG_DAEMON);
+       if (gethostname(hostname, sizeof (hostname) - 1) < 0) {
+               syslog(LOG_ERR, "gethostname: %m");
+               _exit(1);
+       }
+       if (chdir(_PATH_DEV) < 0) {
+               syslog(LOG_ERR, "chdir: %s: %m", _PATH_DEV);
+               _exit(1);
+       }
+       if (argc > 1 && strcmp(argv[1], "-d") == 0)
+               debug = 1;
+       signal(SIGALRM, timeout);
+       alarm(TIMEOUT);
+       for (;;) {
+               extern int errno;
+
+               cc = recv(0, (char *)mp, sizeof (*mp), 0);
+               if (cc != sizeof (*mp)) {
+                       if (cc < 0 && errno != EINTR)
+                               syslog(LOG_WARNING, "recv: %m");
+                       continue;
+               }
+               lastmsgtime = time(0);
+               process_request(mp, &response);
+               /* can block here, is this what I want? */
+               cc = sendto(sockt, (char *)&response,
+                   sizeof (response), 0, (struct sockaddr *)&mp->ctl_addr,
+                   sizeof (mp->ctl_addr));
+               if (cc != sizeof (response))
+                       syslog(LOG_WARNING, "sendto: %m");
+       }
+}
+
+void
+timeout()
+{
+
+       if (time(0) - lastmsgtime >= MAXIDLE)
+               _exit(0);
+       alarm(TIMEOUT);
+}
diff --git a/talkd.tproj/talkd.h b/talkd.tproj/talkd.h
new file mode 100644 (file)
index 0000000..9a686c5
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+extern int     announce __P((CTL_MSG *request, char *remote_machine));
+extern void    do_announce __P((CTL_MSG *mp, CTL_RESPONSE *rp));
+extern int     delete_invite __P((int id_num));
+extern int     find_user __P((char *name, char *tty));
+extern void    insert_table __P((CTL_MSG *request, CTL_RESPONSE *response));
+extern int     new_id __P((void));
+extern void    print_request __P((char *cp, CTL_MSG *mp));
+extern void    print_response __P((char *cp, CTL_RESPONSE *rp));
+extern void    process_request __P((CTL_MSG *mp, CTL_RESPONSE *rp));
diff --git a/tcpdump.tproj/Makefile b/tcpdump.tproj/Makefile
new file mode 100644 (file)
index 0000000..fb9c458
--- /dev/null
@@ -0,0 +1,63 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = tcpdump
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = machdep.h addrtoname.h ntp.h nfsfh.h igrp.h interface.h\
+         os-sunos4.h decnet.h ipx.h mib.h os-ultrix4.h netbios.h\
+         bootp.h ospf.h llc.h nfs.h os-solaris2.h nfsv2.h fddi.h\
+         gnuc.h ethertype.h extract.h appletalk.h
+
+CFILES = addrtoname.c bpf_dump.c machdep.c parsenfsfh.c print-arp.c\
+         print-atalk.c print-atm.c print-bootp.c print-decnet.c\
+         print-domain.c print-dvmrp.c print-egp.c print-ether.c\
+         print-fddi.c print-gre.c print-icmp.c print-igrp.c print-ip.c\
+         print-ipx.c print-isoclns.c print-krb.c print-llc.c\
+         print-netbios.c print-nfs.c print-ntp.c print-null.c\
+         print-ospf.c print-pim.c print-ppp.c print-rip.c print-skip.c\
+         print-sl.c print-snmp.c print-sunrpc.c print-tcp.c\
+         print-tftp.c print-udp.c print-wb.c strcasecmp.c tcpdump.c\
+         util.c version.c vfprintf.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = -lpcap
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -traditional-cpp
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/tcpdump.tproj/Makefile.postamble b/tcpdump.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7823726
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/tcpdump.tproj/Makefile.preamble b/tcpdump.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..faec713
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS =-DRETSIGTYPE=void
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/tcpdump.tproj/PB.project b/tcpdump.tproj/PB.project
new file mode 100644 (file)
index 0000000..143e686
--- /dev/null
@@ -0,0 +1,98 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        CLASSES = (); 
+        FRAMEWORKS = (); 
+        H_FILES = (
+            machdep.h, 
+            addrtoname.h, 
+            ntp.h, 
+            nfsfh.h, 
+            igrp.h, 
+            interface.h, 
+            "os-sunos4.h", 
+            decnet.h, 
+            ipx.h, 
+            mib.h, 
+            "os-ultrix4.h", 
+            netbios.h, 
+            bootp.h, 
+            ospf.h, 
+            llc.h, 
+            nfs.h, 
+            "os-solaris2.h", 
+            nfsv2.h, 
+            fddi.h, 
+            gnuc.h, 
+            ethertype.h, 
+            extract.h, 
+            appletalk.h
+        ); 
+        OTHER_LIBS = (pcap); 
+        OTHER_LINKED = (
+            addrtoname.c, 
+            bpf_dump.c, 
+            machdep.c, 
+            parsenfsfh.c, 
+            "print-arp.c", 
+            "print-atalk.c", 
+            "print-atm.c", 
+            "print-bootp.c", 
+            "print-decnet.c", 
+            "print-domain.c", 
+            "print-dvmrp.c", 
+            "print-egp.c", 
+            "print-ether.c", 
+            "print-fddi.c", 
+            "print-gre.c", 
+            "print-icmp.c", 
+            "print-igrp.c", 
+            "print-ip.c", 
+            "print-ipx.c", 
+            "print-isoclns.c", 
+            "print-krb.c", 
+            "print-llc.c", 
+            "print-netbios.c", 
+            "print-nfs.c", 
+            "print-ntp.c", 
+            "print-null.c", 
+            "print-ospf.c", 
+            "print-pim.c", 
+            "print-ppp.c", 
+            "print-rip.c", 
+            "print-skip.c", 
+            "print-sl.c", 
+            "print-snmp.c", 
+            "print-sunrpc.c", 
+            "print-tcp.c", 
+            "print-tftp.c", 
+            "print-udp.c", 
+            "print-wb.c", 
+            strcasecmp.c, 
+            tcpdump.c, 
+            util.c, 
+            version.c, 
+            vfprintf.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-traditional-cpp"; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = tcpdump; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/tcpdump.tproj/addrtoname.c b/tcpdump.tproj/addrtoname.c
new file mode 100644 (file)
index 0000000..f940348
--- /dev/null
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Internet, ethernet, port, and protocol string to address
+ *  and address to string conversion routines
+ */
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/addrtoname.c,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <pcap.h>
+#include <pcap-namedb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "llc.h"
+
+/* Forwards */
+static RETSIGTYPE nohostname(int);
+
+/*
+ * hash tables for whatever-to-name translations
+ */
+
+#define HASHNAMESIZE 4096
+
+struct hnamemem {
+       u_int32_t addr;
+       char *name;
+       struct hnamemem *nxt;
+};
+
+struct hnamemem hnametable[HASHNAMESIZE];
+struct hnamemem tporttable[HASHNAMESIZE];
+struct hnamemem uporttable[HASHNAMESIZE];
+struct hnamemem eprototable[HASHNAMESIZE];
+struct hnamemem dnaddrtable[HASHNAMESIZE];
+struct hnamemem llcsaptable[HASHNAMESIZE];
+
+struct enamemem {
+       u_short e_addr0;
+       u_short e_addr1;
+       u_short e_addr2;
+       char *e_name;
+       u_char *e_nsap;                 /* used only for nsaptable[] */
+       struct enamemem *e_nxt;
+};
+
+struct enamemem enametable[HASHNAMESIZE];
+struct enamemem nsaptable[HASHNAMESIZE];
+
+struct protoidmem {
+       u_int32_t p_oui;
+       u_short p_proto;
+       char *p_name;
+       struct protoidmem *p_nxt;
+};
+
+struct protoidmem protoidtable[HASHNAMESIZE];
+
+/*
+ * A faster replacement for inet_ntoa().
+ */
+char *
+intoa(u_int32_t addr)
+{
+       register char *cp;
+       register u_int byte;
+       register int n;
+       static char buf[sizeof(".xxx.xxx.xxx.xxx")];
+
+       NTOHL(addr);
+       cp = &buf[sizeof buf];
+       *--cp = '\0';
+
+       n = 4;
+       do {
+               byte = addr & 0xff;
+               *--cp = byte % 10 + '0';
+               byte /= 10;
+               if (byte > 0) {
+                       *--cp = byte % 10 + '0';
+                       byte /= 10;
+                       if (byte > 0)
+                               *--cp = byte + '0';
+               }
+               *--cp = '.';
+               addr >>= 8;
+       } while (--n > 0);
+
+       return cp + 1;
+}
+
+static u_int32_t f_netmask;
+static u_int32_t f_localnet;
+static u_int32_t netmask;
+
+/*
+ * "getname" is written in this atrocious way to make sure we don't
+ * wait forever while trying to get hostnames from yp.
+ */
+#include <setjmp.h>
+
+jmp_buf getname_env;
+
+static RETSIGTYPE
+nohostname(int signo)
+{
+       longjmp(getname_env, 1);
+}
+
+/*
+ * Return a name for the IP address pointed to by ap.  This address
+ * is assumed to be in network byte order.
+ */
+char *
+getname(const u_char *ap)
+{
+       register struct hostent *hp;
+       u_int32_t addr;
+       static struct hnamemem *p;              /* static for longjmp() */
+
+#ifndef LBL_ALIGN
+       addr = *(const u_int32_t *)ap;
+#else
+       /*
+        * Extract 32 bits in network order, dealing with alignment.
+        */
+       switch ((long)ap & 3) {
+
+       case 0:
+               addr = *(u_int32_t *)ap;
+               break;
+
+       case 2:
+#ifdef WORDS_BIGENDIAN
+               addr = ((u_int32_t)*(u_short *)ap << 16) |
+                       (u_int32_t)*(u_short *)(ap + 2);
+#else
+               addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) |
+                       (u_int32_t)*(u_short *)ap;
+#endif
+               break;
+
+       default:
+#ifdef WORDS_BIGENDIAN
+               addr = ((u_int32_t)ap[0] << 24) |
+                       ((u_int32_t)ap[1] << 16) |
+                       ((u_int32_t)ap[2] << 8) |
+                       (u_int32_t)ap[3];
+#else
+               addr = ((u_int32_t)ap[3] << 24) |
+                       ((u_int32_t)ap[2] << 16) |
+                       ((u_int32_t)ap[1] << 8) |
+                       (u_int32_t)ap[0];
+#endif
+               break;
+       }
+#endif
+       p = &hnametable[addr & (HASHNAMESIZE-1)];
+       for (; p->nxt; p = p->nxt) {
+               if (p->addr == addr)
+                       return (p->name);
+       }
+       p->addr = addr;
+       p->nxt = newhnamemem();
+
+       /*
+        * Only print names when:
+        *      (1) -n was not given.
+        *      (2) Address is foreign and -f was given.  If -f was not
+        *          present, f_netmask and f_local are 0 and the second
+        *          test will succeed.
+        *      (3) The host portion is not 0 (i.e., a network address).
+        *      (4) The host portion is not broadcast.
+        */
+       if (!nflag && (addr & f_netmask) == f_localnet
+           && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) {
+               if (!setjmp(getname_env)) {
+                       (void)signal(SIGALRM, nohostname);
+                       (void)alarm(20);
+                       hp = gethostbyaddr((char *)&addr, 4, AF_INET);
+                       (void)alarm(0);
+                       if (hp) {
+                               char *dotp;
+
+                               p->name = savestr(hp->h_name);
+                               if (Nflag) {
+                                       /* Remove domain qualifications */
+                                       dotp = strchr(p->name, '.');
+                                       if (dotp)
+                                               *dotp = '\0';
+                               }
+                               return (p->name);
+                       }
+               }
+       }
+       p->name = savestr(intoa(addr));
+       return (p->name);
+}
+
+static char hex[] = "0123456789abcdef";
+
+
+/* Find the hash node that corresponds the ether address 'ep' */
+
+static inline struct enamemem *
+lookup_emem(const u_char *ep)
+{
+       register u_int i, j, k;
+       struct enamemem *tp;
+
+       k = (ep[0] << 8) | ep[1];
+       j = (ep[2] << 8) | ep[3];
+       i = (ep[4] << 8) | ep[5];
+
+       tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
+       while (tp->e_nxt)
+               if (tp->e_addr0 == i &&
+                   tp->e_addr1 == j &&
+                   tp->e_addr2 == k)
+                       return tp;
+               else
+                       tp = tp->e_nxt;
+       tp->e_addr0 = i;
+       tp->e_addr1 = j;
+       tp->e_addr2 = k;
+       tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
+       if (tp->e_nxt == NULL)
+               error("lookup_emem: calloc");
+
+       return tp;
+}
+
+/* Find the hash node that corresponds the NSAP 'nsap' */
+
+static inline struct enamemem *
+lookup_nsap(register const u_char *nsap)
+{
+       register u_int i, j, k;
+       int nlen = *nsap;
+       struct enamemem *tp;
+       const u_char *ensap = nsap + nlen - 6;
+
+       if (nlen > 6) {
+               k = (ensap[0] << 8) | ensap[1];
+               j = (ensap[2] << 8) | ensap[3];
+               i = (ensap[4] << 8) | ensap[5];
+       }
+       else
+               i = j = k = 0;
+
+       tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
+       while (tp->e_nxt)
+               if (tp->e_addr0 == i &&
+                   tp->e_addr1 == j &&
+                   tp->e_addr2 == k &&
+                   tp->e_nsap[0] == nlen &&
+                   memcmp((char *)&(nsap[1]),
+                       (char *)&(tp->e_nsap[1]), nlen) == 0)
+                       return tp;
+               else
+                       tp = tp->e_nxt;
+       tp->e_addr0 = i;
+       tp->e_addr1 = j;
+       tp->e_addr2 = k;
+       tp->e_nsap = (u_char *)malloc(nlen + 1);
+       if (tp->e_nsap == NULL)
+               error("lookup_nsap: malloc");
+       memcpy(tp->e_nsap, nsap, nlen + 1);
+       tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
+       if (tp->e_nxt == NULL)
+               error("lookup_nsap: calloc");
+
+       return tp;
+}
+
+/* Find the hash node that corresponds the protoid 'pi'. */
+
+static inline struct protoidmem *
+lookup_protoid(const u_char *pi)
+{
+       register u_int i, j;
+       struct protoidmem *tp;
+
+       /* 5 octets won't be aligned */
+       i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
+       j =   (pi[3] << 8) + pi[4];
+       /* XXX should be endian-insensitive, but do big-endian testing  XXX */
+
+       tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
+       while (tp->p_nxt)
+               if (tp->p_oui == i && tp->p_proto == j)
+                       return tp;
+               else
+                       tp = tp->p_nxt;
+       tp->p_oui = i;
+       tp->p_proto = j;
+       tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
+       if (tp->p_nxt == NULL)
+               error("lookup_protoid: calloc");
+
+       return tp;
+}
+
+char *
+etheraddr_string(register const u_char *ep)
+{
+       register u_int i, j;
+       register char *cp;
+       register struct enamemem *tp;
+       char buf[sizeof("00:00:00:00:00:00")];
+
+       tp = lookup_emem(ep);
+       if (tp->e_name)
+               return (tp->e_name);
+#ifdef HAVE_ETHER_NTOHOST
+       if (!nflag) {
+               char buf[128];
+               if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) {
+                       tp->e_name = savestr(buf);
+                       return (tp->e_name);
+               }
+       }
+#endif
+       cp = buf;
+       if ((j = *ep >> 4) != 0)
+               *cp++ = hex[j];
+       *cp++ = hex[*ep++ & 0xf];
+       for (i = 5; (int)--i >= 0;) {
+               *cp++ = ':';
+               if ((j = *ep >> 4) != 0)
+                       *cp++ = hex[j];
+               *cp++ = hex[*ep++ & 0xf];
+       }
+       *cp = '\0';
+       tp->e_name = savestr(buf);
+       return (tp->e_name);
+}
+
+char *
+etherproto_string(u_short port)
+{
+       register char *cp;
+       register struct hnamemem *tp;
+       register u_int32_t i = port;
+       char buf[sizeof("0000")];
+
+       for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+               if (tp->addr == i)
+                       return (tp->name);
+
+       tp->addr = i;
+       tp->nxt = newhnamemem();
+
+       cp = buf;
+       NTOHS(port);
+       *cp++ = hex[port >> 12 & 0xf];
+       *cp++ = hex[port >> 8 & 0xf];
+       *cp++ = hex[port >> 4 & 0xf];
+       *cp++ = hex[port & 0xf];
+       *cp++ = '\0';
+       tp->name = savestr(buf);
+       return (tp->name);
+}
+
+char *
+protoid_string(register const u_char *pi)
+{
+       register u_int i, j;
+       register char *cp;
+       register struct protoidmem *tp;
+       char buf[sizeof("00:00:00:00:00")];
+
+       tp = lookup_protoid(pi);
+       if (tp->p_name)
+               return tp->p_name;
+
+       cp = buf;
+       if ((j = *pi >> 4) != 0)
+               *cp++ = hex[j];
+       *cp++ = hex[*pi++ & 0xf];
+       for (i = 4; (int)--i >= 0;) {
+               *cp++ = ':';
+               if ((j = *pi >> 4) != 0)
+                       *cp++ = hex[j];
+               *cp++ = hex[*pi++ & 0xf];
+       }
+       *cp = '\0';
+       tp->p_name = savestr(buf);
+       return (tp->p_name);
+}
+
+char *
+llcsap_string(u_char sap)
+{
+       register char *cp;
+       register struct hnamemem *tp;
+       register u_int32_t i = sap;
+       char buf[sizeof("sap 00")];
+
+       for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+               if (tp->addr == i)
+                       return (tp->name);
+
+       tp->addr = i;
+       tp->nxt = newhnamemem();
+
+       cp = buf;
+       (void)strcpy(cp, "sap ");
+       cp += strlen(cp);
+       *cp++ = hex[sap >> 4 & 0xf];
+       *cp++ = hex[sap & 0xf];
+       *cp++ = '\0';
+       tp->name = savestr(buf);
+       return (tp->name);
+}
+
+char *
+isonsap_string(const u_char *nsap)
+{
+       register u_int i, nlen = nsap[0];
+       register char *cp;
+       register struct enamemem *tp;
+
+       tp = lookup_nsap(nsap);
+       if (tp->e_name)
+               return tp->e_name;
+
+       tp->e_name = cp = (char *)malloc(nlen * 2 + 2);
+       if (cp == NULL)
+               error("isonsap_string: malloc");
+
+       nsap++;
+       *cp++ = '/';
+       for (i = nlen; (int)--i >= 0;) {
+               *cp++ = hex[*nsap >> 4];
+               *cp++ = hex[*nsap++ & 0xf];
+       }
+       *cp = '\0';
+       return (tp->e_name);
+}
+
+char *
+tcpport_string(u_short port)
+{
+       register struct hnamemem *tp;
+       register u_int32_t i = port;
+       char buf[sizeof("00000")];
+
+       for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+               if (tp->addr == i)
+                       return (tp->name);
+
+       tp->addr = i;
+       tp->nxt = newhnamemem();
+
+       (void)sprintf(buf, "%u", i);
+       tp->name = savestr(buf);
+       return (tp->name);
+}
+
+char *
+udpport_string(register u_short port)
+{
+       register struct hnamemem *tp;
+       register u_int32_t i = port;
+       char buf[sizeof("00000")];
+
+       for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+               if (tp->addr == i)
+                       return (tp->name);
+
+       tp->addr = i;
+       tp->nxt = newhnamemem();
+
+       (void)sprintf(buf, "%u", i);
+       tp->name = savestr(buf);
+       return (tp->name);
+}
+
+static void
+init_servarray(void)
+{
+       struct servent *sv;
+       register struct hnamemem *table;
+       register int i;
+       char buf[sizeof("0000000000")];
+
+       while ((sv = getservent()) != NULL) {
+               int port = ntohs(sv->s_port);
+               i = port & (HASHNAMESIZE-1);
+               if (strcmp(sv->s_proto, "tcp") == 0)
+                       table = &tporttable[i];
+               else if (strcmp(sv->s_proto, "udp") == 0)
+                       table = &uporttable[i];
+               else
+                       continue;
+
+               while (table->name)
+                       table = table->nxt;
+               if (nflag) {
+                       (void)sprintf(buf, "%d", port);
+                       table->name = savestr(buf);
+               } else
+                       table->name = savestr(sv->s_name);
+               table->addr = port;
+               table->nxt = newhnamemem();
+       }
+       endservent();
+}
+
+/*XXX from libbpfc.a */
+extern struct eproto {
+       char *s;
+       u_short p;
+} eproto_db[];
+
+static void
+init_eprotoarray(void)
+{
+       register int i;
+       register struct hnamemem *table;
+
+       for (i = 0; eproto_db[i].s; i++) {
+               int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
+               table = &eprototable[j];
+               while (table->name)
+                       table = table->nxt;
+               table->name = eproto_db[i].s;
+               table->addr = ntohs(eproto_db[i].p);
+               table->nxt = newhnamemem();
+       }
+}
+
+/*
+ * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
+ * types.
+ */
+static void
+init_protoidarray(void)
+{
+       register int i;
+       register struct protoidmem *tp;
+       u_char protoid[5];
+
+       protoid[0] = 0;
+       protoid[1] = 0;
+       protoid[2] = 0;
+       for (i = 0; eproto_db[i].s; i++) {
+               u_short etype = htons(eproto_db[i].p);
+
+               memcpy((char *)&protoid[3], (char *)&etype, 2);
+               tp = lookup_protoid(protoid);
+               tp->p_name = savestr(eproto_db[i].s);
+       }
+}
+
+static struct etherlist {
+       u_char addr[6];
+       char *name;
+} etherlist[] = {
+       {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
+       {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
+};
+
+/*
+ * Initialize the ethers hash table.  We take two different approaches
+ * depending on whether or not the system provides the ethers name
+ * service.  If it does, we just wire in a few names at startup,
+ * and etheraddr_string() fills in the table on demand.  If it doesn't,
+ * then we suck in the entire /etc/ethers file at startup.  The idea
+ * is that parsing the local file will be fast, but spinning through
+ * all the ethers entries via NIS & next_etherent might be very slow.
+ *
+ * XXX pcap_next_etherent doesn't belong in the pcap interface, but
+ * since the pcap module already does name-to-address translation,
+ * it's already does most of the work for the ethernet address-to-name
+ * translation, so we just pcap_next_etherent as a convenience.
+ */
+static void
+init_etherarray(void)
+{
+       register struct etherlist *el;
+       register struct enamemem *tp;
+#ifdef HAVE_ETHER_NTOHOST
+       char name[256];
+#else
+       register struct pcap_etherent *ep;
+       register FILE *fp;
+
+       /* Suck in entire ethers file */
+       fp = fopen(PCAP_ETHERS_FILE, "r");
+       if (fp != NULL) {
+               while ((ep = pcap_next_etherent(fp)) != NULL) {
+                       tp = lookup_emem(ep->addr);
+                       tp->e_name = savestr(ep->name);
+               }
+               (void)fclose(fp);
+       }
+#endif
+
+       /* Hardwire some ethernet names */
+       for (el = etherlist; el->name != NULL; ++el) {
+               tp = lookup_emem(el->addr);
+               /* Don't override existing name */
+               if (tp->e_name != NULL)
+                       continue;
+
+#ifdef HAVE_ETHER_NTOHOST
+                /* Use yp/nis version of name if available */
+                if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
+                        tp->e_name = savestr(name);
+                       continue;
+               }
+#endif
+               tp->e_name = el->name;
+       }
+}
+
+static struct tok llcsap_db[] = {
+       { LLCSAP_NULL,          "null" },
+       { LLCSAP_8021B_I,       "802.1b-gsap" },
+       { LLCSAP_8021B_G,       "802.1b-isap" },
+       { LLCSAP_IP,            "ip-sap" },
+       { LLCSAP_PROWAYNM,      "proway-nm" },
+       { LLCSAP_8021D,         "802.1d" },
+       { LLCSAP_RS511,         "eia-rs511" },
+       { LLCSAP_ISO8208,       "x.25/llc2" },
+       { LLCSAP_PROWAY,        "proway" },
+       { LLCSAP_ISONS,         "iso-clns" },
+       { LLCSAP_GLOBAL,        "global" },
+       { 0,                    NULL }
+};
+
+static void
+init_llcsaparray(void)
+{
+       register int i;
+       register struct hnamemem *table;
+
+       for (i = 0; llcsap_db[i].s != NULL; i++) {
+               table = &llcsaptable[llcsap_db[i].v];
+               while (table->name)
+                       table = table->nxt;
+               table->name = llcsap_db[i].s;
+               table->addr = llcsap_db[i].v;
+               table->nxt = newhnamemem();
+       }
+}
+
+/*
+ * Initialize the address to name translation machinery.  We map all
+ * non-local IP addresses to numeric addresses if fflag is true (i.e.,
+ * to prevent blocking on the nameserver).  localnet is the IP address
+ * of the local network.  mask is its subnet mask.
+ */
+void
+init_addrtoname(int fflag, u_int32_t localnet, u_int32_t mask)
+{
+       netmask = mask;
+       if (fflag) {
+               f_localnet = localnet;
+               f_netmask = mask;
+       }
+       if (nflag)
+               /*
+                * Simplest way to suppress names.
+                */
+               return;
+
+       init_etherarray();
+       init_servarray();
+       init_eprotoarray();
+       init_llcsaparray();
+       init_protoidarray();
+}
+
+char *
+dnaddr_string(u_short dnaddr)
+{
+       register struct hnamemem *tp;
+
+       for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
+            tp = tp->nxt)
+               if (tp->addr == dnaddr)
+                       return (tp->name);
+
+       tp->addr = dnaddr;
+       tp->nxt = newhnamemem();
+       if (nflag)
+               tp->name = dnnum_string(dnaddr);
+       else
+               tp->name = dnname_string(dnaddr);
+
+       return(tp->name);
+}
+
+/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
+struct hnamemem *
+newhnamemem(void)
+{
+       register struct hnamemem *p;
+       static struct hnamemem *ptr = NULL;
+       static u_int num = 0;
+
+       if (num  <= 0) {
+               num = 64;
+               ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
+               if (ptr == NULL)
+                       error("newhnamemem: calloc");
+       }
+       --num;
+       p = ptr++;
+       return (p);
+}
diff --git a/tcpdump.tproj/addrtoname.h b/tcpdump.tproj/addrtoname.h
new file mode 100644 (file)
index 0000000..c40b03f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1992, 1993, 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/addrtoname.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)
+ */
+
+/* Name to address translation routines. */
+
+extern char *etheraddr_string(const u_char *);
+extern char *etherproto_string(u_short);
+extern char *tcpport_string(u_short);
+extern char *udpport_string(u_short);
+extern char *getname(const u_char *);
+extern char *intoa(u_int32_t);
+
+extern void init_addrtoname(int, u_int32_t, u_int32_t);
+extern struct hnamemem *newhnamemem(void);
+
+#define ipaddr_string(p) getname((const u_char *)(p))
diff --git a/tcpdump.tproj/appletalk.h b/tcpdump.tproj/appletalk.h
new file mode 100644 (file)
index 0000000..49690e7
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * AppleTalk protocol formats (courtesy Bill Croft of Stanford/SUMEX).
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/appletalk.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)
+ */
+
+struct LAP {
+       u_char  dst;
+       u_char  src;
+       u_char  type;
+};
+#define lapShortDDP    1       /* short DDP type */
+#define lapDDP         2       /* DDP type */
+#define lapKLAP                'K'     /* Kinetics KLAP type */
+
+/* Datagram Delivery Protocol */
+
+struct atDDP {
+       u_short length;
+       u_short checksum;
+       u_short dstNet;
+       u_short srcNet;
+       u_char  dstNode;
+       u_char  srcNode;
+       u_char  dstSkt;
+       u_char  srcSkt;
+       u_char  type;
+};
+
+struct atShortDDP {
+       u_short length;
+       u_char  dstSkt;
+       u_char  srcSkt;
+       u_char  type;
+};
+
+#define        ddpMaxWKS       0x7F
+#define        ddpMaxData      586
+#define        ddpLengthMask   0x3FF
+#define        ddpHopShift     10
+#define        ddpSize         13      /* size of DDP header (avoid struct padding) */
+#define        ddpSSize        5
+#define        ddpWKS          128     /* boundary of DDP well known sockets */
+#define        ddpRTMP         1       /* RTMP type */
+#define        ddpRTMPrequest  5       /* RTMP request type */
+#define        ddpNBP          2       /* NBP type */
+#define        ddpATP          3       /* ATP type */
+#define        ddpECHO         4       /* ECHO type */
+#define        ddpIP           22      /* IP type */
+#define        ddpARP          23      /* ARP type */
+#define        ddpKLAP         0x4b    /* Kinetics KLAP type */
+
+
+/* AppleTalk Transaction Protocol */
+
+struct atATP {
+       u_char  control;
+       u_char  bitmap;
+       u_short transID;
+       int32_t userData;
+};
+
+#define        atpReqCode      0x40
+#define        atpRspCode      0x80
+#define        atpRelCode      0xC0
+#define        atpXO           0x20
+#define        atpEOM          0x10
+#define        atpSTS          0x08
+#define        atpFlagMask     0x3F
+#define        atpControlMask  0xF8
+#define        atpMaxNum       8
+#define        atpMaxData      578
+
+
+/* AppleTalk Echo Protocol */
+
+struct atEcho {
+       u_char  echoFunction;
+       u_char  *echoData;
+};
+
+#define echoSkt                4               /* the echoer socket */
+#define echoSize       1               /* size of echo header */
+#define echoRequest    1               /* echo request */
+#define echoReply      2               /* echo request */
+
+
+/* Name Binding Protocol */
+
+struct atNBP {
+       u_char  control;
+       u_char  id;
+};
+
+struct atNBPtuple {
+       u_short net;
+       u_char  node;
+       u_char  skt;
+       u_char  enumerator;
+};
+
+#define        nbpBrRq         0x10
+#define        nbpLkUp         0x20
+#define        nbpLkUpReply    0x30
+
+#define        nbpNIS          2
+#define        nbpTupleMax     15
+
+#define        nbpHeaderSize   2
+#define nbpTupleSize   5
+
+#define nbpSkt         2               /* NIS */
+
+
+/* Routing Table Maint. Protocol */
+
+#define        rtmpSkt         1       /* number of RTMP socket */
+#define        rtmpSize        4       /* minimum size */
+#define        rtmpTupleSize   3
+
+
+/* Zone Information Protocol */
+
+struct zipHeader {
+       u_char  command;
+       u_char  netcount;
+};
+
+#define        zipHeaderSize   2
+#define        zipQuery        1
+#define        zipReply        2
+#define        zipTakedown     3
+#define        zipBringup      4
+#define        ddpZIP          6
+#define        zipSkt          6
+#define        GetMyZone       7
+#define        GetZoneList     8
+
+/*
+ * UDP port range used for ddp-in-udp encapsulation is 16512-16639
+ * for client sockets (128-255) and 200-327 for server sockets
+ * (0-127).  We also try to recognize the pre-April 88 server
+ * socket range of 768-895.
+ */
+#define atalk_port(p) \
+       (((unsigned)((p) - 16512) < 128) || \
+        ((unsigned)((p) - 200) < 128) || \
+        ((unsigned)((p) - 768) < 128))
diff --git a/tcpdump.tproj/bootp.h b/tcpdump.tproj/bootp.h
new file mode 100644 (file)
index 0000000..74dc2c2
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/bootp.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) */
+/*
+ * Bootstrap Protocol (BOOTP).  RFC951 and RFC1048.
+ *
+ * This file specifies the "implementation-independent" BOOTP protocol
+ * information which is common to both client and server.
+ *
+ * Copyright 1988 by Carnegie Mellon.
+ *
+ * Permission to use, copy, modify, and distribute this program for any
+ * purpose and without fee is hereby granted, provided that this copyright
+ * and permission notice appear on all copies and supporting documentation,
+ * the name of Carnegie Mellon not be used in advertising or publicity
+ * pertaining to distribution of the program without specific prior
+ * permission, and notice be given in supporting documentation that copying
+ * and distribution is by permission of Carnegie Mellon and Stanford
+ * University.  Carnegie Mellon makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ */
+
+
+struct bootp {
+       unsigned char   bp_op;          /* packet opcode type */
+       unsigned char   bp_htype;       /* hardware addr type */
+       unsigned char   bp_hlen;        /* hardware addr length */
+       unsigned char   bp_hops;        /* gateway hops */
+       u_int32_t       bp_xid;         /* transaction ID */
+       unsigned short  bp_secs;        /* seconds since boot began */
+       unsigned short  bp_unused;
+       struct in_addr  bp_ciaddr;      /* client IP address */
+       struct in_addr  bp_yiaddr;      /* 'your' IP address */
+       struct in_addr  bp_siaddr;      /* server IP address */
+       struct in_addr  bp_giaddr;      /* gateway IP address */
+       unsigned char   bp_chaddr[16];  /* client hardware address */
+       unsigned char   bp_sname[64];   /* server host name */
+       unsigned char   bp_file[128];   /* boot file name */
+       unsigned char   bp_vend[64];    /* vendor-specific area */
+};
+
+/*
+ * UDP port numbers, server and client.
+ */
+#define        IPPORT_BOOTPS           67
+#define        IPPORT_BOOTPC           68
+
+#define BOOTREPLY              2
+#define BOOTREQUEST            1
+
+
+/*
+ * Vendor magic cookie (v_magic) for CMU
+ */
+#define VM_CMU         "CMU"
+
+/*
+ * Vendor magic cookie (v_magic) for RFC1048
+ */
+#define VM_RFC1048     { 99, 130, 83, 99 }
+
+\f
+
+/*
+ * RFC1048 tag values used to specify what information is being supplied in
+ * the vendor field of the packet.
+ */
+
+#define TAG_PAD                        ((unsigned char)   0)
+#define TAG_SUBNET_MASK                ((unsigned char)   1)
+#define TAG_TIME_OFFSET                ((unsigned char)   2)
+#define TAG_GATEWAY            ((unsigned char)   3)
+#define TAG_TIME_SERVER                ((unsigned char)   4)
+#define TAG_NAME_SERVER                ((unsigned char)   5)
+#define TAG_DOMAIN_SERVER      ((unsigned char)   6)
+#define TAG_LOG_SERVER         ((unsigned char)   7)
+#define TAG_COOKIE_SERVER      ((unsigned char)   8)
+#define TAG_LPR_SERVER         ((unsigned char)   9)
+#define TAG_IMPRESS_SERVER     ((unsigned char)  10)
+#define TAG_RLP_SERVER         ((unsigned char)  11)
+#define TAG_HOSTNAME           ((unsigned char)  12)
+#define TAG_BOOTSIZE           ((unsigned char)  13)
+#define TAG_END                        ((unsigned char) 255)
+/* RFC1497 tags */
+#define        TAG_DUMPPATH            ((unsigned char)  14)
+#define        TAG_DOMAINNAME          ((unsigned char)  15)
+#define        TAG_SWAP_SERVER         ((unsigned char)  16)
+#define        TAG_ROOTPATH            ((unsigned char)  17)
+#define        TAG_EXTPATH             ((unsigned char)  18)
+
+
+
+/*
+ * "vendor" data permitted for CMU bootp clients.
+ */
+
+struct cmu_vend {
+       unsigned char   v_magic[4];     /* magic number */
+       u_int32_t       v_flags;        /* flags/opcodes, etc. */
+       struct in_addr  v_smask;        /* Subnet mask */
+       struct in_addr  v_dgate;        /* Default gateway */
+       struct in_addr  v_dns1, v_dns2; /* Domain name servers */
+       struct in_addr  v_ins1, v_ins2; /* IEN-116 name servers */
+       struct in_addr  v_ts1, v_ts2;   /* Time servers */
+       unsigned char   v_unused[24];   /* currently unused */
+};
+
+
+/* v_flags values */
+#define VF_SMASK       1       /* Subnet mask field contains valid data */
diff --git a/tcpdump.tproj/bpf_dump.c b/tcpdump.tproj/bpf_dump.c
new file mode 100644 (file)
index 0000000..5c29e59
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/bpf_dump.c,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <pcap.h>
+#include <stdio.h>
+
+#include "interface.h"
+
+extern void bpf_dump(struct bpf_program *, int);
+
+void
+bpf_dump(struct bpf_program *p, int option)
+{
+       struct bpf_insn *insn;
+       int i;
+       int n = p->bf_len;
+
+       insn = p->bf_insns;
+       if (option > 2) {
+               printf("%d\n", n);
+               for (i = 0; i < n; ++insn, ++i) {
+                       printf("%u %u %u %u\n", insn->code,
+                              insn->jt, insn->jf, insn->k);
+               }
+               return ;
+       }
+       if (option > 1) {
+               for (i = 0; i < n; ++insn, ++i)
+                       printf("{ 0x%x, %d, %d, 0x%08x },\n",
+                              insn->code, insn->jt, insn->jf, insn->k);
+               return;
+       }
+       for (i = 0; i < n; ++insn, ++i) {
+#ifdef BDEBUG
+               extern int bids[];
+               printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1);
+#endif
+               puts(bpf_image(insn, i));
+       }
+}
diff --git a/tcpdump.tproj/decnet.h b/tcpdump.tproj/decnet.h
new file mode 100644 (file)
index 0000000..37a6127
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/decnet.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)
+ */
+
+typedef unsigned char byte[1];         /* single byte field */
+typedef unsigned char word[2];         /* 2 byte field */
+typedef unsigned char longword[4];     /* 4 bytes field */
+
+/*
+ * Definitions for DECNET Phase IV protocol headers
+ */
+union etheraddress {
+       unsigned char   dne_addr[6];            /* full ethernet address */
+       struct {
+               unsigned char dne_hiord[4];     /* DECnet HIORD prefix */
+               unsigned char dne_nodeaddr[2];  /* DECnet node address */
+       } dne_remote;
+};
+
+typedef union etheraddress etheraddr;  /* Ethernet address */
+
+#define HIORD 0x000400aa               /* high 32-bits of address (swapped) */
+
+#define AREAMASK       0176000         /* mask for area field */
+#define        AREASHIFT       10              /* bit-offset for area field */
+#define NODEMASK       01777           /* mask for node address field */
+
+#define DN_MAXADDL     20              /* max size of DECnet address */
+struct dn_naddr {
+       unsigned short  a_len;          /* length of address */
+       unsigned char a_addr[DN_MAXADDL]; /* address as bytes */
+};
+
+/*
+ * Define long and short header formats.
+ */
+struct shorthdr
+  {
+    byte       sh_flags;               /* route flags */
+    word       sh_dst;                 /* destination node address */
+    word       sh_src;                 /* source node address */
+    byte       sh_visits;              /* visit count */
+  };
+
+struct longhdr
+  {
+    byte       lg_flags;               /* route flags */
+    byte       lg_darea;               /* destination area (reserved) */
+    byte       lg_dsarea;              /* destination subarea (reserved) */
+    etheraddr  lg_dst;                 /* destination id */
+    byte       lg_sarea;               /* source area (reserved) */
+    byte       lg_ssarea;              /* source subarea (reserved) */
+    etheraddr  lg_src;                 /* source id */
+    byte       lg_nextl2;              /* next level 2 router (reserved) */
+    byte       lg_visits;              /* visit count */
+    byte       lg_service;             /* service class (reserved) */
+    byte       lg_pt;                  /* protocol type (reserved) */
+  };
+
+union routehdr
+  {
+    struct shorthdr rh_short;          /* short route header */
+    struct longhdr rh_long;            /* long route header */
+  };
+
+/*
+ * Define the values of various fields in the protocol messages.
+ *
+ * 1. Data packet formats.
+ */
+#define RMF_MASK       7               /* mask for message type */
+#define RMF_SHORT      2               /* short message format */
+#define RMF_LONG       6               /* long message format */
+#ifndef RMF_RQR
+#define RMF_RQR                010             /* request return to sender */
+#define RMF_RTS                020             /* returning to sender */
+#define RMF_IE         040             /* intra-ethernet packet */
+#endif /* RMR_RQR */
+#define RMF_FVER       0100            /* future version flag */
+#define RMF_PAD                0200            /* pad field */
+#define RMF_PADMASK    0177            /* pad field mask */
+
+#define VIS_MASK       077             /* visit field mask */
+
+/*
+ * 2. Control packet formats.
+ */
+#define RMF_CTLMASK    017             /* mask for message type */
+#define RMF_CTLMSG     01              /* control message indicator */
+#define RMF_INIT       01              /* initialization message */
+#define RMF_VER                03              /* verification message */
+#define RMF_TEST       05              /* hello and test message */
+#define RMF_L1ROUT     07              /* level 1 routing message */
+#define RMF_L2ROUT     011             /* level 2 routing message */
+#define RMF_RHELLO     013             /* router hello message */
+#define RMF_EHELLO     015             /* endnode hello message */
+
+#define TI_L2ROUT      01              /* level 2 router */
+#define TI_L1ROUT      02              /* level 1 router */
+#define TI_ENDNODE     03              /* endnode */
+#define TI_VERIF       04              /* verification required */
+#define TI_BLOCK       010             /* blocking requested */
+
+#define VE_VERS                2               /* version number (2) */
+#define VE_ECO         0               /* ECO number */
+#define VE_UECO                0               /* user ECO number (0) */
+
+#define P3_VERS                1               /* phase III version number (1) */
+#define P3_ECO         3               /* ECO number (3) */
+#define P3_UECO                0               /* user ECO number (0) */
+
+#define II_L2ROUT      01              /* level 2 router */
+#define II_L1ROUT      02              /* level 1 router */
+#define II_ENDNODE     03              /* endnode */
+#define II_VERIF       04              /* verification required */
+#define II_NOMCAST     040             /* no multicast traffic accepted */
+#define II_BLOCK       0100            /* blocking requested */
+#define II_TYPEMASK    03              /* mask for node type */
+
+#define TESTDATA       0252            /* test data bytes */
+#define TESTLEN                1               /* length of transmitted test data */
+
+/*
+ * Define control message formats.
+ */
+struct initmsgIII                      /* phase III initialization message */
+  {
+    byte       inIII_flags;            /* route flags */
+    word       inIII_src;              /* source node address */
+    byte       inIII_info;             /* routing layer information */
+    word       inIII_blksize;          /* maximum data link block size */
+    byte       inIII_vers;             /* version number */
+    byte       inIII_eco;              /* ECO number */
+    byte       inIII_ueco;             /* user ECO number */
+    byte       inIII_rsvd;             /* reserved image field */
+  };
+
+struct initmsg                         /* initialization message */
+  {
+    byte       in_flags;               /* route flags */
+    word       in_src;                 /* source node address */
+    byte       in_info;                /* routing layer information */
+    word       in_blksize;             /* maximum data link block size */
+    byte       in_vers;                /* version number */
+    byte       in_eco;                 /* ECO number */
+    byte       in_ueco;                /* user ECO number */
+    word       in_hello;               /* hello timer */
+    byte       in_rsvd;                /* reserved image field */
+  };
+
+struct verifmsg                                /* verification message */
+  {
+    byte       ve_flags;               /* route flags */
+    word       ve_src;                 /* source node address */
+    byte       ve_fcnval;              /* function value image field */
+  };
+
+struct testmsg                         /* hello and test message */
+  {
+    byte       te_flags;               /* route flags */
+    word       te_src;                 /* source node address */
+    byte       te_data;                /* test data image field */
+  };
+
+struct l1rout                          /* level 1 routing message */
+  {
+    byte       r1_flags;               /* route flags */
+    word       r1_src;                 /* source node address */
+    byte       r1_rsvd;                /* reserved field */
+  };
+
+struct l2rout                          /* level 2 routing message */
+  {
+    byte       r2_flags;               /* route flags */
+    word       r2_src;                 /* source node address */
+    byte       r2_rsvd;                /* reserved field */
+  };
+
+struct rhellomsg                       /* router hello message */
+  {
+    byte       rh_flags;               /* route flags */
+    byte       rh_vers;                /* version number */
+    byte       rh_eco;                 /* ECO number */
+    byte       rh_ueco;                /* user ECO number */
+    etheraddr  rh_src;                 /* source id */
+    byte       rh_info;                /* routing layer information */
+    word       rh_blksize;             /* maximum data link block size */
+    byte       rh_priority;            /* router's priority */
+    byte       rh_area;                /* reserved */
+    word       rh_hello;               /* hello timer */
+    byte       rh_mpd;                 /* reserved */
+  };
+
+struct ehellomsg                       /* endnode hello message */
+  {
+    byte       eh_flags;               /* route flags */
+    byte       eh_vers;                /* version number */
+    byte       eh_eco;                 /* ECO number */
+    byte       eh_ueco;                /* user ECO number */
+    etheraddr  eh_src;                 /* source id */
+    byte       eh_info;                /* routing layer information */
+    word       eh_blksize;             /* maximum data link block size */
+    byte       eh_area;                /* area (reserved) */
+    byte       eh_seed[8];             /* verification seed */
+    etheraddr  eh_router;              /* designated router */
+    word       eh_hello;               /* hello timer */
+    byte       eh_mpd;                 /* (reserved) */
+    byte       eh_data;                /* test data image field */
+  };
+
+union controlmsg
+  {
+    struct initmsg     cm_init;        /* initialization message */
+    struct verifmsg    cm_ver;         /* verification message */
+    struct testmsg     cm_test;        /* hello and test message */
+    struct l1rout      cm_l1rou;       /* level 1 routing message */
+    struct l2rout      cm_l2rout;      /* level 2 routing message */
+    struct rhellomsg   cm_rhello;      /* router hello message */
+    struct ehellomsg   cm_ehello;      /* endnode hello message */
+  };
+
+/* Macros for decoding routing-info fields */
+#define        RI_COST(x)      ((x)&0777)
+#define        RI_HOPS(x)      (((x)>>10)&037)
+\f
+/*
+ * NSP protocol fields and values.
+ */
+
+#define NSP_TYPEMASK 014               /* mask to isolate type code */
+#define NSP_SUBMASK 0160               /* mask to isolate subtype code */
+#define NSP_SUBSHFT 4                  /* shift to move subtype code */
+
+#define MFT_DATA 0                     /* data message */
+#define MFT_ACK  04                    /* acknowledgement message */
+#define MFT_CTL  010                   /* control message */
+
+#define MFS_ILS  020                   /* data or I/LS indicator */
+#define MFS_BOM  040                   /* beginning of message (data) */
+#define MFS_MOM  0                     /* middle of message (data) */
+#define MFS_EOM  0100                  /* end of message (data) */
+#define MFS_INT  040                   /* interrupt message */
+
+#define MFS_DACK 0                     /* data acknowledgement */
+#define MFS_IACK 020                   /* I/LS acknowledgement */
+#define MFS_CACK 040                   /* connect acknowledgement */
+
+#define MFS_NOP  0                     /* no operation */
+#define MFS_CI   020                   /* connect initiate */
+#define MFS_CC   040                   /* connect confirm */
+#define MFS_DI   060                   /* disconnect initiate */
+#define MFS_DC   0100                  /* disconnect confirm */
+#define MFS_RCI  0140                  /* retransmitted connect initiate */
+
+#define SGQ_ACK  0100000               /* ack */
+#define SGQ_NAK  0110000               /* negative ack */
+#define SGQ_OACK 0120000               /* other channel ack */
+#define SGQ_ONAK 0130000               /* other channel negative ack */
+#define SGQ_MASK 07777                 /* mask to isolate seq # */
+#define SGQ_OTHER 020000               /* other channel qualifier */
+#define SGQ_DELAY 010000               /* ack delay flag */
+
+#define SGQ_EOM  0100000               /* pseudo flag for end-of-message */
+
+#define LSM_MASK 03                    /* mask for modifier field */
+#define LSM_NOCHANGE 0                 /* no change */
+#define LSM_DONOTSEND 1                        /* do not send data */
+#define LSM_SEND 2                     /* send data */
+
+#define LSI_MASK 014                   /* mask for interpretation field */
+#define LSI_DATA 0                     /* data segment or message count */
+#define LSI_INTR 4                     /* interrupt request count */
+#define LSI_INTM 0377                  /* funny marker for int. message */
+
+#define COS_MASK 014                   /* mask for flow control field */
+#define COS_NONE 0                     /* no flow control */
+#define COS_SEGMENT 04                 /* segment flow control */
+#define COS_MESSAGE 010                        /* message flow control */
+#define COS_CRYPTSER 020               /* cryptographic services requested */
+#define COS_DEFAULT 1                  /* default value for field */
+
+#define COI_MASK 3                     /* mask for version field */
+#define COI_32 0                       /* version 3.2 */
+#define COI_31 1                       /* version 3.1 */
+#define COI_40 2                       /* version 4.0 */
+#define COI_41 3                       /* version 4.1 */
+
+#define MNU_MASK 140                   /* mask for session control version */
+#define MNU_10 000                             /* session V1.0 */
+#define MNU_20 040                             /* session V2.0 */
+#define MNU_ACCESS 1                   /* access control present */
+#define MNU_USRDATA 2                  /* user data field present */
+#define MNU_INVKPROXY 4                        /* invoke proxy field present */
+#define MNU_UICPROXY 8                 /* use uic-based proxy */
+
+#define DC_NORESOURCES 1               /* no resource reason code */
+#define DC_NOLINK 41                   /* no link terminate reason code */
+#define DC_COMPLETE 42                 /* disconnect complete reason code */
+
+#define DI_NOERROR 0                   /* user disconnect */
+#define DI_SHUT 3                      /* node is shutting down */
+#define DI_NOUSER 4                    /* destination end user does not exist */
+#define DI_INVDEST 5                   /* invalid end user destination */
+#define DI_REMRESRC 6                  /* insufficient remote resources */
+#define DI_TPA 8                       /* third party abort */
+#define DI_PROTOCOL 7                  /* protocol error discovered */
+#define DI_ABORT 9                     /* user abort */
+#define DI_LOCALRESRC 32               /* insufficient local resources */
+#define DI_REMUSERRESRC 33             /* insufficient remote user resources */
+#define DI_BADACCESS 34                        /* bad access control information */
+#define DI_BADACCNT 36                 /* bad ACCOUNT information */
+#define DI_CONNECTABORT 38             /* connect request cancelled */
+#define DI_TIMEDOUT 38                 /* remote node or user crashed */
+#define DI_UNREACHABLE 39              /* local timers expired due to ... */
+#define DI_BADIMAGE 43                 /* bad image data in connect */
+#define DI_SERVMISMATCH 54             /* cryptographic service mismatch */
+
+#define UC_OBJREJECT 0                 /* object rejected connect */
+#define UC_USERDISCONNECT 0            /* user disconnect */
+#define UC_RESOURCES 1                 /* insufficient resources (local or remote) */
+#define UC_NOSUCHNODE 2                        /* unrecognized node name */
+#define UC_REMOTESHUT 3                        /* remote node shutting down */
+#define UC_NOSUCHOBJ 4                 /* unrecognized object */
+#define UC_INVOBJFORMAT 5              /* invalid object name format */
+#define UC_OBJTOOBUSY 6                        /* object too busy */
+#define UC_NETWORKABORT 8              /* network abort */
+#define UC_USERABORT 9                 /* user abort */
+#define UC_INVNODEFORMAT 10            /* invalid node name format */
+#define UC_LOCALSHUT 11                        /* local node shutting down */
+#define UC_ACCESSREJECT 34             /* invalid access control information */
+#define UC_NORESPONSE 38               /* no response from object */
+#define UC_UNREACHABLE 39              /* node unreachable */
+
+/*
+ * NSP message formats.
+ */
+struct nsphdr                          /* general nsp header */
+  {
+    byte       nh_flags;               /* message flags */
+    word       nh_dst;                 /* destination link address */
+    word       nh_src;                 /* source link address */
+  };
+
+struct seghdr                          /* data segment header */
+  {
+    byte       sh_flags;               /* message flags */
+    word       sh_dst;                 /* destination link address */
+    word       sh_src;                 /* source link address */
+    word       sh_seq[3];              /* sequence numbers */
+  };
+
+struct minseghdr                       /* minimum data segment header */
+  {
+    byte       ms_flags;               /* message flags */
+    word       ms_dst;                 /* destination link address */
+    word       ms_src;                 /* source link address */
+    word       ms_seq;                 /* sequence number */
+  };
+
+struct lsmsg                           /* link service message (after hdr) */
+  {
+    byte       ls_lsflags;             /* link service flags */
+    byte       ls_fcval;               /* flow control value */
+  };
+
+struct ackmsg                          /* acknowledgement message */
+  {
+    byte       ak_flags;               /* message flags */
+    word       ak_dst;                 /* destination link address */
+    word       ak_src;                 /* source link address */
+    word       ak_acknum[2];           /* acknowledgement numbers */
+  };
+
+struct minackmsg                       /* minimum acknowledgement message */
+  {
+    byte       mk_flags;               /* message flags */
+    word       mk_dst;                 /* destination link address */
+    word       mk_src;                 /* source link address */
+    word       mk_acknum;              /* acknowledgement number */
+  };
+
+struct ciackmsg                                /* connect acknowledgement message */
+  {
+    byte       ck_flags;               /* message flags */
+    word       ck_dst;                 /* destination link address */
+  };
+
+struct cimsg                           /* connect initiate message */
+  {
+    byte       ci_flags;               /* message flags */
+    word       ci_dst;                 /* destination link address (0) */
+    word       ci_src;                 /* source link address */
+    byte       ci_services;            /* requested services */
+    byte       ci_info;                /* information */
+    word       ci_segsize;             /* maximum segment size */
+  };
+
+struct ccmsg                           /* connect confirm message */
+  {
+    byte       cc_flags;               /* message flags */
+    word       cc_dst;                 /* destination link address */
+    word       cc_src;                 /* source link address */
+    byte       cc_services;            /* requested services */
+    byte       cc_info;                /* information */
+    word       cc_segsize;             /* maximum segment size */
+    byte       cc_optlen;              /* optional data length */
+  };
+
+struct cnmsg                           /* generic connect message */
+  {
+    byte       cn_flags;               /* message flags */
+    word       cn_dst;                 /* destination link address */
+    word       cn_src;                 /* source link address */
+    byte       cn_services;            /* requested services */
+    byte       cn_info;                /* information */
+    word       cn_segsize;             /* maximum segment size */
+  };
+
+struct dimsg                           /* disconnect initiate message */
+  {
+    byte       di_flags;               /* message flags */
+    word       di_dst;                 /* destination link address */
+    word       di_src;                 /* source link address */
+    word       di_reason;              /* reason code */
+    byte       di_optlen;              /* optional data length */
+  };
+
+struct dcmsg                           /* disconnect confirm message */
+  {
+    byte       dc_flags;               /* message flags */
+    word       dc_dst;                 /* destination link address */
+    word       dc_src;                 /* source link address */
+    word       dc_reason;              /* reason code */
+  };
diff --git a/tcpdump.tproj/ethertype.h b/tcpdump.tproj/ethertype.h
new file mode 100644 (file)
index 0000000..43726ac
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993, 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/ethertype.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)
+ */
+
+/* Types missing from some systems */
+
+#ifndef ETHERTYPE_NS
+#define ETHERTYPE_NS           0x0600
+#endif
+#ifndef        ETHERTYPE_SPRITE
+#define        ETHERTYPE_SPRITE        0x0500
+#endif
+#ifndef ETHERTYPE_TRAIL
+#define ETHERTYPE_TRAIL                0x1000
+#endif
+#ifndef        ETHERTYPE_MOPDL
+#define        ETHERTYPE_MOPDL         0x6001
+#endif
+#ifndef        ETHERTYPE_MOPRC
+#define        ETHERTYPE_MOPRC         0x6002
+#endif
+#ifndef        ETHERTYPE_DN
+#define        ETHERTYPE_DN            0x6003
+#endif
+#ifndef        ETHERTYPE_LAT
+#define        ETHERTYPE_LAT           0x6004
+#endif
+#ifndef ETHERTYPE_SCA
+#define ETHERTYPE_SCA          0x6007
+#endif
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP       0x8035
+#endif
+#ifndef        ETHERTYPE_LANBRIDGE
+#define        ETHERTYPE_LANBRIDGE     0x8038
+#endif
+#ifndef        ETHERTYPE_DECDNS
+#define        ETHERTYPE_DECDNS        0x803c
+#endif
+#ifndef        ETHERTYPE_DECDTS
+#define        ETHERTYPE_DECDTS        0x803e
+#endif
+#ifndef        ETHERTYPE_VEXP
+#define        ETHERTYPE_VEXP          0x805b
+#endif
+#ifndef        ETHERTYPE_VPROD
+#define        ETHERTYPE_VPROD         0x805c
+#endif
+#ifndef ETHERTYPE_ATALK
+#define ETHERTYPE_ATALK                0x809b
+#endif
+#ifndef ETHERTYPE_AARP
+#define ETHERTYPE_AARP         0x80f3
+#endif
+#ifndef        ETHERTYPE_LOOPBACK
+#define        ETHERTYPE_LOOPBACK      0x9000
+#endif
diff --git a/tcpdump.tproj/extract.h b/tcpdump.tproj/extract.h
new file mode 100644 (file)
index 0000000..f3213d4
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/extract.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)
+ */
+
+/* Network to host order macros */
+
+#ifdef LBL_ALIGN
+#define EXTRACT_16BITS(p) \
+       ((u_short)*((u_char *)(p) + 0) << 8 | \
+       (u_short)*((u_char *)(p) + 1))
+#define EXTRACT_32BITS(p) \
+       ((u_int32_t)*((u_char *)(p) + 0) << 24 | \
+       (u_int32_t)*((u_char *)(p) + 1) << 16 | \
+       (u_int32_t)*((u_char *)(p) + 2) << 8 | \
+       (u_int32_t)*((u_char *)(p) + 3))
+#else
+#define EXTRACT_16BITS(p) \
+       ((u_short)ntohs(*(u_short *)(p)))
+#define EXTRACT_32BITS(p) \
+       ((u_int32_t)ntohl(*(u_int32_t *)(p)))
+#endif
+
+#define EXTRACT_24BITS(p) \
+       ((u_int32_t)*((u_char *)(p) + 0) << 16 | \
+       (u_int32_t)*((u_char *)(p) + 1) << 8 | \
+       (u_int32_t)*((u_char *)(p) + 2))
+
+/* Little endian protocol host order macros */
+
+#define EXTRACT_LE_8BITS(p) (*(p))
+#define EXTRACT_LE_16BITS(p) \
+       ((u_short)*((u_char *)(p) + 1) << 8 | \
+       (u_short)*((u_char *)(p) + 0))
+#define EXTRACT_LE_32BITS(p) \
+       ((u_int32_t)*((u_char *)(p) + 3) << 24 | \
+       (u_int32_t)*((u_char *)(p) + 2) << 16 | \
+       (u_int32_t)*((u_char *)(p) + 1) << 8 | \
+       (u_int32_t)*((u_char *)(p) + 0))
diff --git a/tcpdump.tproj/fddi.h b/tcpdump.tproj/fddi.h
new file mode 100644 (file)
index 0000000..21920f4
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/fddi.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)
+ */
+
+/*
+ * Based on Ultrix if_fddi.h
+ */
+
+/*
+ * This stuff should come from a system header file, but there's no
+ * obviously portable way to do that and it's not really going
+ * to change from system to system (except for the padding business).
+ */
+
+struct fddi_header {
+       u_char  fddi_fc;                /* frame control */
+       u_char  fddi_dhost[6];
+       u_char  fddi_shost[6];
+};
+
+
+/* Useful values for fddi_fc (frame control) field */
+
+/*
+ * FDDI Frame Control bits
+ */
+#define        FDDIFC_C                0x80            /* Class bit */
+#define        FDDIFC_L                0x40            /* Address length bit */
+#define        FDDIFC_F                0x30            /* Frame format bits */
+#define        FDDIFC_Z                0x0f            /* Control bits */
+
+/*
+ * FDDI Frame Control values. (48-bit addressing only).
+ */
+#define        FDDIFC_VOID             0x40            /* Void frame */
+#define        FDDIFC_NRT              0x80            /* Nonrestricted token */
+#define        FDDIFC_RT               0xc0            /* Restricted token */
+#define        FDDIFC_SMT_INFO         0x41            /* SMT Info */
+#define        FDDIFC_SMT_NSA          0x4F            /* SMT Next station adrs */
+#define        FDDIFC_MAC_BEACON       0xc2            /* MAC Beacon frame */
+#define        FDDIFC_MAC_CLAIM        0xc3            /* MAC Claim frame */
+#define        FDDIFC_LLC_ASYNC        0x50            /* Async. LLC frame */
+#define        FDDIFC_LLC_SYNC         0xd0            /* Sync. LLC frame */
+#define        FDDIFC_IMP_ASYNC        0x60            /* Implementor Async. */
+#define        FDDIFC_IMP_SYNC         0xe0            /* Implementor Synch. */
+#define FDDIFC_SMT             0x40            /* SMT frame */
+#define FDDIFC_MAC             0xc0            /* MAC frame */
+
+#define        FDDIFC_CLFF             0xF0            /* Class/Length/Format bits */
+#define        FDDIFC_ZZZZ             0x0F            /* Control bits */
diff --git a/tcpdump.tproj/gnuc.h b/tcpdump.tproj/gnuc.h
new file mode 100644 (file)
index 0000000..a88d32c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/gnuc.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) */
+
+/* Define __P() macro, if necessary */
+#ifndef __P
+#if __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+/* inline foo */
+#ifdef __GNUC__
+#define inline __inline
+#else
+#define inline
+#endif
+
+/*
+ * Handle new and old "dead" routine prototypes
+ *
+ * For example:
+ *
+ *     __dead void foo(void) __attribute__((volatile));
+ *
+ */
+#ifdef __GNUC__
+#ifndef __dead
+#define __dead volatile
+#endif
+#if __GNUC__ < 2  || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
+#else
+#ifndef __dead
+#define __dead
+#endif
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
diff --git a/tcpdump.tproj/igrp.h b/tcpdump.tproj/igrp.h
new file mode 100644 (file)
index 0000000..ec55bdf
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* Cisco IGRP definitions */
+
+/* IGRP Header */
+
+struct igrphdr {
+#ifdef WORDS_BIGENDIAN
+       u_char ig_v:4;          /* protocol version number */
+       u_char ig_op:4;         /* opcode */
+#else
+       u_char ig_op:4;         /* opcode */
+       u_char ig_v:4;          /* protocol version number */
+#endif
+       u_char ig_ed;           /* edition number */
+       u_short ig_as;          /* autonomous system number */
+       u_short ig_ni;          /* number of subnet in local net */
+       u_short ig_ns;          /* number of networks in AS */
+       u_short ig_nx;          /* number of networks ouside AS */
+       u_short ig_sum;         /* checksum of IGRP header & data */
+};
+
+#define IGRP_UPDATE    1
+#define IGRP_REQUEST   2
+
+/* IGRP routing entry */
+
+struct igrprte {
+       u_char igr_net[3];      /* 3 significant octets of IP address */
+       u_char igr_dly[3];      /* delay in tens of microseconds */
+       u_char igr_bw[3];       /* bandwidth in units of 1 kb/s */
+       u_char igr_mtu[2];      /* MTU in octets */
+       u_char igr_rel;         /* percent packets successfully tx/rx */
+       u_char igr_ld;          /* percent of channel occupied */
+       u_char igr_hct;         /* hop count */
+};
+
+#define IGRP_RTE_SIZE  14      /* don't believe sizeof ! */
diff --git a/tcpdump.tproj/interface.h b/tcpdump.tproj/interface.h
new file mode 100644 (file)
index 0000000..089c4dd
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/interface.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)
+ */
+
+#ifndef tcpdump_interface_h
+#define tcpdump_interface_h
+#ifndef        IPPROTO_ND
+#define        IPPROTO_ND      77
+#endif
+
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+struct tok {
+       int v;                  /* value */
+       char *s;                /* string */
+};
+
+extern int dflag;              /* print filter code */
+extern int eflag;              /* print ethernet header */
+extern int nflag;              /* leave addresses as numbers */
+extern int Nflag;              /* remove domains from printed host names */
+extern int qflag;              /* quick (shorter) output */
+extern int Sflag;              /* print raw TCP sequence numbers */
+extern int tflag;              /* print packet arrival time */
+extern int vflag;              /* verbose */
+extern int xflag;              /* print packet in hex */
+
+extern int packettype;         /* as specified by -T */
+#define PT_VAT         1       /* Visual Audio Tool */
+#define PT_WB          2       /* distributed White Board */
+#define PT_RPC         3       /* Remote Procedure Call */
+#define PT_RTP         4       /* Real-Time Applications protocol */
+#define PT_RTCP                5       /* Real-Time Applications control protocol */
+
+#ifndef min
+#define min(a,b) ((a)>(b)?(b):(a))
+#endif
+#ifndef max
+#define max(a,b) ((b)>(a)?(b):(a))
+#endif
+
+/*
+ * The default snapshot length.  This value allows most printers to print
+ * useful information while keeping the amount of unwanted data down.
+ * In particular, it allows for an ethernet header, tcp/ip header, and
+ * 14 bytes of data (assuming no ip options).
+ */
+#define DEFAULT_SNAPLEN 68
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifdef ETHER_HEADER_HAS_EA
+#define ESRC(ep) ((ep)->ether_shost.ether_addr_octet)
+#define EDST(ep) ((ep)->ether_dhost.ether_addr_octet)
+#else
+#define ESRC(ep) ((ep)->ether_shost)
+#define EDST(ep) ((ep)->ether_dhost)
+#endif
+
+#ifdef ETHER_ARP_HAS_X
+#define SHA(ap) ((ap)->arp_xsha)
+#define THA(ap) ((ap)->arp_xtha)
+#define SPA(ap) ((ap)->arp_xspa)
+#define TPA(ap) ((ap)->arp_xtpa)
+#else
+#ifdef ETHER_ARP_HAS_EA
+#define SHA(ap) ((ap)->arp_sha.ether_addr_octet)
+#define THA(ap) ((ap)->arp_tha.ether_addr_octet)
+#else
+#define SHA(ap) ((ap)->arp_sha)
+#define THA(ap) ((ap)->arp_tha)
+#endif
+#define SPA(ap) ((ap)->arp_spa)
+#define TPA(ap) ((ap)->arp_tpa)
+#endif
+
+#ifndef NTOHL
+#define NTOHL(x)       (x) = ntohl(x)
+#define NTOHS(x)       (x) = ntohs(x)
+#define HTONL(x)       (x) = htonl(x)
+#define HTONS(x)       (x) = htons(x)
+#endif
+#endif
+
+extern char *program_name;     /* used to generate self-identifying messages */
+
+extern int32_t thiszone;       /* seconds offset from gmt to local time */
+
+extern int snaplen;
+/* global pointers to beginning and end of current packet (during printing) */
+extern const u_char *packetp;
+extern const u_char *snapend;
+
+/* True if  "l" bytes of "var" were captured */
+#define TTEST2(var, l) ((u_char *)&(var) <= snapend - (l))
+
+/* True if "var" was captured */
+#define TTEST(var) TTEST2(var, sizeof(var))
+
+/* Bail if "l" bytes of "var" were not captured */
+#define TCHECK2(var, l) if (!TTEST2(var, l)) goto trunc
+
+/* Bail if "var" was not captured */
+#define TCHECK(var) TCHECK2(var, sizeof(var))
+
+#ifdef __STDC__
+struct timeval;
+#endif
+
+extern void ts_print(const struct timeval *);
+extern int32_t gmt2local(void);
+
+extern int fn_print(const u_char *, const u_char *);
+extern int fn_printn(const u_char *, u_int, const u_char *);
+extern const char *tok2str(const struct tok *, const char *, int);
+extern char *dnaddr_string(u_short);
+extern char *savestr(const char *);
+
+extern void wrapup(int);
+
+#if __STDC__
+extern __dead void error(const char *, ...)
+    __attribute__((volatile, format (printf, 1, 2)));
+extern void warning(const char *, ...) __attribute__ ((format (printf, 1, 2)));
+#endif
+
+extern char *read_infile(char *);
+extern char *copy_argv(char **);
+
+extern char *isonsap_string(const u_char *);
+extern char *llcsap_string(u_char);
+extern char *protoid_string(const u_char *);
+extern char *dnname_string(u_short);
+extern char *dnnum_string(u_short);
+
+/* The printer routines. */
+
+#ifdef __STDC__
+struct pcap_pkthdr;
+#endif
+
+extern int ether_encap_print(u_short, const u_char *, u_int, u_int);
+extern int llc_print(const u_char *, u_int, u_int, const u_char *,
+       const u_char *);
+extern void aarp_print(const u_char *, u_int);
+extern void arp_print(const u_char *, u_int, u_int);
+extern void atalk_print(const u_char *, u_int);
+extern void atm_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
+extern void bootp_print(const u_char *, u_int, u_short, u_short);
+extern void decnet_print(const u_char *, u_int, u_int);
+extern void default_print(const u_char *, u_int);
+extern void default_print_unaligned(const u_char *, u_int);
+extern void dvmrp_print(const u_char *, u_int);
+extern void egp_print(const u_char *, u_int, const u_char *);
+extern void ether_if_print(u_char *, const struct pcap_pkthdr *,
+       const u_char *);
+extern void fddi_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
+extern void gre_print(const u_char *, u_int);
+extern void icmp_print(const u_char *, const u_char *);
+extern void igrp_print(const u_char *, u_int, const u_char *);
+extern void ip_print(const u_char *, u_int);
+extern void ipx_print(const u_char *, u_int);
+extern void isoclns_print(const u_char *, u_int, u_int, const u_char *,
+       const u_char *);
+extern void krb_print(const u_char *, u_int);
+extern void nfsreply_print(const u_char *, u_int, const u_char *);
+extern void nfsreq_print(const u_char *, u_int, const u_char *);
+extern void ns_print(const u_char *, u_int);
+extern void ntp_print(const u_char *, u_int);
+extern void null_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
+extern void ospf_print(const u_char *, u_int, const u_char *);
+extern void pim_print(const u_char *, u_int);
+extern void ppp_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
+extern void rip_print(const u_char *, u_int);
+extern void sl_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
+extern void snmp_print(const u_char *, u_int);
+extern void sunrpcrequest_print(const u_char *, u_int, const u_char *);
+extern void tcp_print(const u_char *, u_int, const u_char *);
+extern void tftp_print(const u_char *, u_int);
+extern void udp_print(const u_char *, u_int, const u_char *);
+extern void wb_print(const void *, u_int);
diff --git a/tcpdump.tproj/ipx.h b/tcpdump.tproj/ipx.h
new file mode 100644 (file)
index 0000000..e1dda81
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * IPX protocol formats 
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/ipx.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $
+ */
+
+/* well-known sockets */
+#define        IPX_SKT_NCP             0x0451
+#define        IPX_SKT_SAP             0x0452
+#define        IPX_SKT_RIP             0x0453
+#define        IPX_SKT_NETBIOS         0x0455
+#define        IPX_SKT_DIAGNOSTICS     0x0456
+
+/* IPX transport header */
+struct ipxHdr {
+    u_short    cksum;          /* Checksum */
+    u_short    length;         /* Length, in bytes, including header */
+    u_char     tCtl;           /* Transport Control (i.e. hop count) */
+    u_char     pType;          /* Packet Type (i.e. level 2 protocol) */
+    u_short    dstNet[2];      /* destination net */
+    u_char     dstNode[6];     /* destination node */
+    u_short    dstSkt;         /* destination socket */
+    u_short    srcNet[2];      /* source net */
+    u_char     srcNode[6];     /* source node */
+    u_short    srcSkt;         /* source socket */
+} ipx_hdr_t;
+
+#define ipxSize        30
+
diff --git a/tcpdump.tproj/llc.h b/tcpdump.tproj/llc.h
new file mode 100644 (file)
index 0000000..4432514
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/llc.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)
+ */
+
+/*
+ * This stuff should come from a system header file, but there's no
+ * obviously portable way to do that and it's not really going
+ * to change from system to system.
+ */
+
+/*
+ * A somewhat abstracted view of the LLC header
+ */
+
+struct llc {
+       u_char dsap;
+       u_char ssap;
+       union {
+               u_char u_ctl;
+               u_short is_ctl;
+               struct {
+                       u_char snap_ui;
+                       u_char snap_pi[5];
+               } snap;
+               struct {
+                       u_char snap_ui;
+                       u_char snap_orgcode[3];
+                       u_char snap_ethertype[2];
+               } snap_ether;
+       } ctl;
+};
+
+#define        llcui           ctl.snap.snap_ui
+#define        llcpi           ctl.snap.snap_pi
+#define        orgcode         ctl.snap_ether.snap_orgcode
+#define        ethertype       ctl.snap_ether.snap_ethertype
+#define        llcis           ctl.is_ctl
+#define        llcu            ctl.u_ctl
+
+#define        LLC_U_FMT       3
+#define        LLC_GSAP        1
+#define LLC_S_FMT      1
+
+#define        LLC_U_POLL      0x10
+#define        LLC_IS_POLL     0x0001
+#define        LLC_XID_FI      0x81
+
+#define        LLC_U_CMD(u)    ((u) & 0xef)
+#define        LLC_UI          0x03
+#define        LLC_UA          0x63
+#define        LLC_DISC        0x43
+#define        LLC_DM          0x0f
+#define        LLC_SABME       0x6f
+#define        LLC_TEST        0xe3
+#define        LLC_XID         0xaf
+#define        LLC_FRMR        0x87
+
+#define        LLC_S_CMD(is)   (((is) >> 10) & 0x03)
+#define        LLC_RR          0x0100
+#define        LLC_RNR         0x0500
+#define        LLC_REJ         0x0900
+
+#define LLC_IS_NR(is)  (((is) >> 9) & 0x7f)
+#define LLC_I_NS(is)   (((is) >> 1) & 0x7f)
+
+#ifndef LLCSAP_NULL
+#define        LLCSAP_NULL             0x00
+#endif
+#ifndef LLCSAP_GLOBAL
+#define        LLCSAP_GLOBAL           0xff
+#endif
+#ifndef LLCSAP_8021B
+#define        LLCSAP_8021B_I          0x02
+#endif
+#ifndef LLCSAP_8021B
+#define        LLCSAP_8021B_G          0x03
+#endif
+#ifndef LLCSAP_IP
+#define        LLCSAP_IP               0x06
+#endif
+#ifndef LLCSAP_PROWAYNM
+#define        LLCSAP_PROWAYNM         0x0e
+#endif
+#ifndef LLCSAP_8021D
+#define        LLCSAP_8021D            0x42
+#endif
+#ifndef LLCSAP_RS511
+#define        LLCSAP_RS511            0x4e
+#endif
+#ifndef LLCSAP_ISO8208
+#define        LLCSAP_ISO8208          0x7e
+#endif
+#ifndef LLCSAP_PROWAY
+#define        LLCSAP_PROWAY           0x8e
+#endif
+#ifndef LLCSAP_SNAP
+#define        LLCSAP_SNAP             0xaa
+#endif
+#ifndef LLCSAP_ISONS
+#define        LLCSAP_ISONS            0xfe
+#endif
diff --git a/tcpdump.tproj/machdep.c b/tcpdump.tproj/machdep.c
new file mode 100644 (file)
index 0000000..df136f4
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/machdep.c,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#ifdef __osf__
+#include <sys/sysinfo.h>
+#include <sys/proc.h>
+#endif
+
+#include <pcap.h>
+
+#include "machdep.h"
+
+int
+abort_on_misalignment(char *ebuf)
+{
+#ifdef __osf__
+       static int buf[2] = { SSIN_UACPROC, UAC_SIGBUS };
+
+       if (setsysinfo(SSI_NVPAIRS, (caddr_t)buf, 1, 0, 0) < 0) {
+               (void)sprintf(ebuf, "setsysinfo: %s", pcap_strerror(errno));
+               return (-1);
+       }
+#endif
+       return (0);
+}
diff --git a/tcpdump.tproj/machdep.h b/tcpdump.tproj/machdep.h
new file mode 100644 (file)
index 0000000..7e8d45a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/machdep.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)
+ */
+#ifndef tcpdump_machdep_h
+#define tcpdump_machdep_h
+
+int abort_on_misalignment(char *);
+#endif
diff --git a/tcpdump.tproj/mib.h b/tcpdump.tproj/mib.h
new file mode 100644 (file)
index 0000000..454d6b2
--- /dev/null
@@ -0,0 +1,1279 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * This file was generated by tcpdump/makemib on Wed Sep 26 12:12:31 EDT 1990
+ * You probably don't want to edit this by hand!
+ *
+ * struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer
+};
+ */
+
+/* parse problem: new name "mib" for mgmt.mib(1) ignored */
+/* parse problem: no parent for 0.nullSpecific(0) */
+struct obj
+_proteon_obj = {
+       "proteon", 1, 0,
+       NULL, NULL
+},
+_ibm_obj = {
+       "ibm", 2, 0,
+       NULL, &_proteon_obj
+},
+_cmu_obj = {
+       "cmu", 3, 0,
+       NULL, &_ibm_obj
+},
+_unix_obj = {
+       "unix", 4, 0,
+       NULL, &_cmu_obj
+},
+_acc_obj = {
+       "acc", 5, 0,
+       NULL, &_unix_obj
+},
+_twg_obj = {
+       "twg", 6, 0,
+       NULL, &_acc_obj
+},
+_cayman_obj = {
+       "cayman", 7, 0,
+       NULL, &_twg_obj
+},
+_nysernet_obj = {
+       "nysernet", 8, 0,
+       NULL, &_cayman_obj
+},
+_cisco_obj = {
+       "cisco", 9, 0,
+       NULL, &_nysernet_obj
+},
+_nsc_obj = {
+       "nsc", 10, 0,
+       NULL, &_cisco_obj
+},
+_hp_obj = {
+       "hp", 11, 0,
+       NULL, &_nsc_obj
+},
+_epilogue_obj = {
+       "epilogue", 12, 0,
+       NULL, &_hp_obj
+},
+_utennessee_obj = {
+       "utennessee", 13, 0,
+       NULL, &_epilogue_obj
+},
+_bbn_obj = {
+       "bbn", 14, 0,
+       NULL, &_utennessee_obj
+},
+_xylogics_obj = {
+       "xylogics", 15, 0,
+       NULL, &_bbn_obj
+},
+_unisys_obj = {
+       "unisys", 16, 0,
+       NULL, &_xylogics_obj
+},
+_canstar_obj = {
+       "canstar", 17, 0,
+       NULL, &_unisys_obj
+},
+_wellfleet_obj = {
+       "wellfleet", 18, 0,
+       NULL, &_canstar_obj
+},
+_trw_obj = {
+       "trw", 19, 0,
+       NULL, &_wellfleet_obj
+},
+_mit_obj = {
+       "mit", 20, 0,
+       NULL, &_trw_obj
+},
+_eon_obj = {
+       "eon", 21, 0,
+       NULL, &_mit_obj
+},
+_spartacus_obj = {
+       "spartacus", 22, 0,
+       NULL, &_eon_obj
+},
+_excelan_obj = {
+       "excelan", 23, 0,
+       NULL, &_spartacus_obj
+},
+_spider_obj = {
+       "spider", 24, 0,
+       NULL, &_excelan_obj
+},
+_nsfnet_obj = {
+       "nsfnet", 25, 0,
+       NULL, &_spider_obj
+},
+_sytek_obj = {
+       "sytek", 26, 0,
+       NULL, &_nsfnet_obj
+},
+_intergraph_obj = {
+       "intergraph", 27, 0,
+       NULL, &_sytek_obj
+},
+_interlan_obj = {
+       "interlan", 28, 0,
+       NULL, &_intergraph_obj
+},
+_vitalink_obj = {
+       "vitalink", 29, 0,
+       NULL, &_interlan_obj
+},
+_ulana_obj = {
+       "ulana", 30, 0,
+       NULL, &_vitalink_obj
+},
+_nswc_obj = {
+       "nswc", 31, 0,
+       NULL, &_ulana_obj
+},
+_santacruzoperation_obj = {
+       "santacruzoperation", 32, 0,
+       NULL, &_nswc_obj
+},
+_xyplex_obj = {
+       "xyplex", 33, 0,
+       NULL, &_santacruzoperation_obj
+},
+_cray_obj = {
+       "cray", 34, 0,
+       NULL, &_xyplex_obj
+},
+_bellnorthernresearch_obj = {
+       "bellnorthernresearch", 35, 0,
+       NULL, &_cray_obj
+},
+_dec_obj = {
+       "dec", 36, 0,
+       NULL, &_bellnorthernresearch_obj
+},
+_touch_obj = {
+       "touch", 37, 0,
+       NULL, &_dec_obj
+},
+_networkresearchcorp_obj = {
+       "networkresearchcorp", 38, 0,
+       NULL, &_touch_obj
+},
+_baylor_obj = {
+       "baylor", 39, 0,
+       NULL, &_networkresearchcorp_obj
+},
+_nmfeccllnl_obj = {
+       "nmfeccllnl", 40, 0,
+       NULL, &_baylor_obj
+},
+_sri_obj = {
+       "sri", 41, 0,
+       NULL, &_nmfeccllnl_obj
+},
+_sun_obj = {
+       "sun", 42, 0,
+       NULL, &_sri_obj
+},
+_3com_obj = {
+       "3com", 43, 0,
+       NULL, &_sun_obj
+},
+_cmc_obj = {
+       "cmc", 44, 0,
+       NULL, &_3com_obj
+},
+_synoptics_obj = {
+       "synoptics", 45, 0,
+       NULL, &_cmc_obj
+},
+_cheyenne_obj = {
+       "cheyenne", 46, 0,
+       NULL, &_synoptics_obj
+},
+_prime_obj = {
+       "prime", 47, 0,
+       NULL, &_cheyenne_obj
+},
+_mcnc_obj = {
+       "mcnc", 48, 0,
+       NULL, &_prime_obj
+},
+_chipcom_obj = {
+       "chipcom", 49, 0,
+       NULL, &_mcnc_obj
+},
+_opticaldatasystems_obj = {
+       "opticaldatasystems", 50, 0,
+       NULL, &_chipcom_obj
+},
+_gated_obj = {
+       "gated", 51, 0,
+       NULL, &_opticaldatasystems_obj
+},
+_cabletron_obj = {
+       "cabletron", 52, 0,
+       NULL, &_gated_obj
+},
+_apollo_obj = {
+       "apollo", 53, 0,
+       NULL, &_cabletron_obj
+},
+_desktalksystems_obj = {
+       "desktalksystems", 54, 0,
+       NULL, &_apollo_obj
+},
+_ssds_obj = {
+       "ssds", 55, 0,
+       NULL, &_desktalksystems_obj
+},
+_castlerock_obj = {
+       "castlerock", 56, 0,
+       NULL, &_ssds_obj
+},
+_mips_obj = {
+       "mips", 57, 0,
+       NULL, &_castlerock_obj
+},
+_tgv_obj = {
+       "tgv", 58, 0,
+       NULL, &_mips_obj
+},
+_silicongraphics_obj = {
+       "silicongraphics", 59, 0,
+       NULL, &_tgv_obj
+},
+_ubc_obj = {
+       "ubc", 60, 0,
+       NULL, &_silicongraphics_obj
+},
+_merit_obj = {
+       "merit", 61, 0,
+       NULL, &_ubc_obj
+},
+_fibercom_obj = {
+       "fibercom", 62, 0,
+       NULL, &_merit_obj
+},
+_apple_obj = {
+       "apple", 63, 0,
+       NULL, &_fibercom_obj
+},
+_gandalf_obj = {
+       "gandalf", 64, 0,
+       NULL, &_apple_obj
+},
+_dartmouth_obj = {
+       "dartmouth", 65, 0,
+       NULL, &_gandalf_obj
+},
+_davidsystems_obj = {
+       "davidsystems", 66, 0,
+       NULL, &_dartmouth_obj
+},
+_reuter_obj = {
+       "reuter", 67, 0,
+       NULL, &_davidsystems_obj
+},
+_cornell_obj = {
+       "cornell", 68, 0,
+       NULL, &_reuter_obj
+},
+_tmac_obj = {
+       "tmac", 69, 0,
+       NULL, &_cornell_obj
+},
+_locus_obj = {
+       "locus", 70, 0,
+       NULL, &_tmac_obj
+},
+_nasa_obj = {
+       "nasa", 71, 0,
+       NULL, &_locus_obj
+},
+_retix_obj = {
+       "retix", 72, 0,
+       NULL, &_nasa_obj
+},
+_boeing_obj = {
+       "boeing", 73, 0,
+       NULL, &_retix_obj
+},
+_att_obj = {
+       "att", 74, 0,
+       NULL, &_boeing_obj
+},
+_ungermannbass_obj = {
+       "ungermannbass", 75, 0,
+       NULL, &_att_obj
+},
+_digitalanalysis_obj = {
+       "digitalanalysis", 76, 0,
+       NULL, &_ungermannbass_obj
+},
+_hplanman_obj = {
+       "hplanman", 77, 0,
+       NULL, &_digitalanalysis_obj
+},
+_netlabs_obj = {
+       "netlabs", 78, 0,
+       NULL, &_hplanman_obj
+},
+_icl_obj = {
+       "icl", 79, 0,
+       NULL, &_netlabs_obj
+},
+_auspex_obj = {
+       "auspex", 80, 0,
+       NULL, &_icl_obj
+},
+_lannet_obj = {
+       "lannet", 81, 0,
+       NULL, &_auspex_obj
+},
+_ncd_obj = {
+       "ncd", 82, 0,
+       NULL, &_lannet_obj
+},
+_raycom_obj = {
+       "raycom", 83, 0,
+       NULL, &_ncd_obj
+},
+_pirellifocom_obj = {
+       "pirellifocom", 84, 0,
+       NULL, &_raycom_obj
+},
+_datability_obj = {
+       "datability", 85, 0,
+       NULL, &_pirellifocom_obj
+},
+_networkappltech_obj = {
+       "networkappltech", 86, 0,
+       NULL, &_datability_obj
+},
+_link_obj = {
+       "link", 87, 0,
+       NULL, &_networkappltech_obj
+},
+_nyu_obj = {
+       "nyu", 88, 0,
+       NULL, &_link_obj
+},
+_rnd_obj = {
+       "rnd", 89, 0,
+       NULL, &_nyu_obj
+},
+_intercon_obj = {
+       "intercon", 90, 0,
+       NULL, &_rnd_obj
+},
+_learningtree_obj = {
+       "learningtree", 91, 0,
+       NULL, &_intercon_obj
+},
+_webstercomputer_obj = {
+       "webstercomputer", 92, 0,
+       NULL, &_learningtree_obj
+},
+_frontier_obj = {
+       "frontier", 93, 0,
+       NULL, &_webstercomputer_obj
+},
+_nokia_obj = {
+       "nokia", 94, 0,
+       NULL, &_frontier_obj
+},
+_allenbradley_obj = {
+       "allenbradley", 95, 0,
+       NULL, &_nokia_obj
+},
+_cern_obj = {
+       "cern", 96, 0,
+       NULL, &_allenbradley_obj
+},
+_sigma_obj = {
+       "sigma", 97, 0,
+       NULL, &_cern_obj
+},
+_emergingtech_obj = {
+       "emergingtech", 98, 0,
+       NULL, &_sigma_obj
+},
+_snmpresearch_obj = {
+       "snmpresearch", 99, 0,
+       NULL, &_emergingtech_obj
+},
+_ohiostate_obj = {
+       "ohiostate", 100, 0,
+       NULL, &_snmpresearch_obj
+},
+_ultra_obj = {
+       "ultra", 101, 0,
+       NULL, &_ohiostate_obj
+},
+_ccur_obj = {
+       "ccur", 136, 0,
+       NULL, &_ultra_obj
+},
+_enterprises_obj = {
+       "enterprises", 1, 0,
+       &_ccur_obj, NULL
+},
+_snmpInPkts_obj = {
+       "snmpInPkts", 1, 0,
+       NULL, NULL
+},
+_snmpOutPkts_obj = {
+       "snmpOutPkts", 2, 0,
+       NULL, &_snmpInPkts_obj
+},
+_snmpInBadVersions_obj = {
+       "snmpInBadVersions", 3, 0,
+       NULL, &_snmpOutPkts_obj
+},
+_snmpInBadCommunityNames_obj = {
+       "snmpInBadCommunityNames", 4, 0,
+       NULL, &_snmpInBadVersions_obj
+},
+_snmpInBadCommunityUses_obj = {
+       "snmpInBadCommunityUses", 5, 0,
+       NULL, &_snmpInBadCommunityNames_obj
+},
+_snmpInASNParseErrs_obj = {
+       "snmpInASNParseErrs", 6, 0,
+       NULL, &_snmpInBadCommunityUses_obj
+},
+_snmpInBadTypes_obj = {
+       "snmpInBadTypes", 7, 0,
+       NULL, &_snmpInASNParseErrs_obj
+},
+_snmpInTooBigs_obj = {
+       "snmpInTooBigs", 8, 0,
+       NULL, &_snmpInBadTypes_obj
+},
+_snmpInNoSuchNames_obj = {
+       "snmpInNoSuchNames", 9, 0,
+       NULL, &_snmpInTooBigs_obj
+},
+_snmpInBadValues_obj = {
+       "snmpInBadValues", 10, 0,
+       NULL, &_snmpInNoSuchNames_obj
+},
+_snmpInReadOnlys_obj = {
+       "snmpInReadOnlys", 11, 0,
+       NULL, &_snmpInBadValues_obj
+},
+_snmpInGenErrs_obj = {
+       "snmpInGenErrs", 12, 0,
+       NULL, &_snmpInReadOnlys_obj
+},
+_snmpInTotalReqVars_obj = {
+       "snmpInTotalReqVars", 13, 0,
+       NULL, &_snmpInGenErrs_obj
+},
+_snmpInTotalSetVars_obj = {
+       "snmpInTotalSetVars", 14, 0,
+       NULL, &_snmpInTotalReqVars_obj
+},
+_snmpInGetRequests_obj = {
+       "snmpInGetRequests", 15, 0,
+       NULL, &_snmpInTotalSetVars_obj
+},
+_snmpInGetNexts_obj = {
+       "snmpInGetNexts", 16, 0,
+       NULL, &_snmpInGetRequests_obj
+},
+_snmpInSetRequests_obj = {
+       "snmpInSetRequests", 17, 0,
+       NULL, &_snmpInGetNexts_obj
+},
+_snmpInGetResponses_obj = {
+       "snmpInGetResponses", 18, 0,
+       NULL, &_snmpInSetRequests_obj
+},
+_snmpInTraps_obj = {
+       "snmpInTraps", 19, 0,
+       NULL, &_snmpInGetResponses_obj
+},
+_snmpOutTooBigs_obj = {
+       "snmpOutTooBigs", 20, 0,
+       NULL, &_snmpInTraps_obj
+},
+_snmpOutNoSuchNames_obj = {
+       "snmpOutNoSuchNames", 21, 0,
+       NULL, &_snmpOutTooBigs_obj
+},
+_snmpOutBadValues_obj = {
+       "snmpOutBadValues", 22, 0,
+       NULL, &_snmpOutNoSuchNames_obj
+},
+_snmpOutReadOnlys_obj = {
+       "snmpOutReadOnlys", 23, 0,
+       NULL, &_snmpOutBadValues_obj
+},
+_snmpOutGenErrs_obj = {
+       "snmpOutGenErrs", 24, 0,
+       NULL, &_snmpOutReadOnlys_obj
+},
+_snmpOutGetRequests_obj = {
+       "snmpOutGetRequests", 25, 0,
+       NULL, &_snmpOutGenErrs_obj
+},
+_snmpOutGetNexts_obj = {
+       "snmpOutGetNexts", 26, 0,
+       NULL, &_snmpOutGetRequests_obj
+},
+_snmpOutSetRequests_obj = {
+       "snmpOutSetRequests", 27, 0,
+       NULL, &_snmpOutGetNexts_obj
+},
+_snmpOutGetResponses_obj = {
+       "snmpOutGetResponses", 28, 0,
+       NULL, &_snmpOutSetRequests_obj
+},
+_snmpOutTraps_obj = {
+       "snmpOutTraps", 29, 0,
+       NULL, &_snmpOutGetResponses_obj
+},
+_snmpEnableAuthTraps_obj = {
+       "snmpEnableAuthTraps", 30, 0,
+       NULL, &_snmpOutTraps_obj
+},
+_egpNeighState_obj = {
+       "egpNeighState", 1, 0,
+       NULL, NULL
+},
+_egpNeighAddr_obj = {
+       "egpNeighAddr", 2, 0,
+       NULL, &_egpNeighState_obj
+},
+_egpNeighAs_obj = {
+       "egpNeighAs", 3, 0,
+       NULL, &_egpNeighAddr_obj
+},
+_egpNeighInMsgs_obj = {
+       "egpNeighInMsgs", 4, 0,
+       NULL, &_egpNeighAs_obj
+},
+_egpNeighInErrs_obj = {
+       "egpNeighInErrs", 5, 0,
+       NULL, &_egpNeighInMsgs_obj
+},
+_egpNeighOutMsgs_obj = {
+       "egpNeighOutMsgs", 6, 0,
+       NULL, &_egpNeighInErrs_obj
+},
+_egpNeighOutErrs_obj = {
+       "egpNeighOutErrs", 7, 0,
+       NULL, &_egpNeighOutMsgs_obj
+},
+_egpNeighInErrMsgs_obj = {
+       "egpNeighInErrMsgs", 8, 0,
+       NULL, &_egpNeighOutErrs_obj
+},
+_egpNeighOutErrMsgs_obj = {
+       "egpNeighOutErrMsgs", 9, 0,
+       NULL, &_egpNeighInErrMsgs_obj
+},
+_egpNeighStateUps_obj = {
+       "egpNeighStateUps", 10, 0,
+       NULL, &_egpNeighOutErrMsgs_obj
+},
+_egpNeighStateDowns_obj = {
+       "egpNeighStateDowns", 11, 0,
+       NULL, &_egpNeighStateUps_obj
+},
+_egpNeighIntervalHello_obj = {
+       "egpNeighIntervalHello", 12, 0,
+       NULL, &_egpNeighStateDowns_obj
+},
+_egpNeighIntervalPoll_obj = {
+       "egpNeighIntervalPoll", 13, 0,
+       NULL, &_egpNeighIntervalHello_obj
+},
+_egpNeighMode_obj = {
+       "egpNeighMode", 14, 0,
+       NULL, &_egpNeighIntervalPoll_obj
+},
+_egpNeighEventTrigger_obj = {
+       "egpNeighEventTrigger", 15, 0,
+       NULL, &_egpNeighMode_obj
+},
+_egpNeighEntry_obj = {
+       "egpNeighEntry", 1, 0,
+       &_egpNeighEventTrigger_obj, NULL
+},
+_egpInMsgs_obj = {
+       "egpInMsgs", 1, 0,
+       NULL, NULL
+},
+_egpInErrors_obj = {
+       "egpInErrors", 2, 0,
+       NULL, &_egpInMsgs_obj
+},
+_egpOutMsgs_obj = {
+       "egpOutMsgs", 3, 0,
+       NULL, &_egpInErrors_obj
+},
+_egpOutErrors_obj = {
+       "egpOutErrors", 4, 0,
+       NULL, &_egpOutMsgs_obj
+},
+_egpNeighTable_obj = {
+       "egpNeighTable", 5, 0,
+       &_egpNeighEntry_obj, &_egpOutErrors_obj
+},
+_egpAs_obj = {
+       "egpAs", 6, 0,
+       NULL, &_egpNeighTable_obj
+},
+_udpLocalAddress_obj = {
+       "udpLocalAddress", 1, 0,
+       NULL, NULL
+},
+_udpLocalPort_obj = {
+       "udpLocalPort", 2, 0,
+       NULL, &_udpLocalAddress_obj
+},
+_udpEntry_obj = {
+       "udpEntry", 1, 0,
+       &_udpLocalPort_obj, NULL
+},
+_udpInDatagrams_obj = {
+       "udpInDatagrams", 1, 0,
+       NULL, NULL
+},
+_udpNoPorts_obj = {
+       "udpNoPorts", 2, 0,
+       NULL, &_udpInDatagrams_obj
+},
+_udpInErrors_obj = {
+       "udpInErrors", 3, 0,
+       NULL, &_udpNoPorts_obj
+},
+_udpOutDatagrams_obj = {
+       "udpOutDatagrams", 4, 0,
+       NULL, &_udpInErrors_obj
+},
+_udpTable_obj = {
+       "udpTable", 5, 0,
+       &_udpEntry_obj, &_udpOutDatagrams_obj
+},
+_tcpConnState_obj = {
+       "tcpConnState", 1, 0,
+       NULL, NULL
+},
+_tcpConnLocalAddress_obj = {
+       "tcpConnLocalAddress", 2, 0,
+       NULL, &_tcpConnState_obj
+},
+_tcpConnLocalPort_obj = {
+       "tcpConnLocalPort", 3, 0,
+       NULL, &_tcpConnLocalAddress_obj
+},
+_tcpConnRemAddress_obj = {
+       "tcpConnRemAddress", 4, 0,
+       NULL, &_tcpConnLocalPort_obj
+},
+_tcpConnRemPort_obj = {
+       "tcpConnRemPort", 5, 0,
+       NULL, &_tcpConnRemAddress_obj
+},
+_tcpConnEntry_obj = {
+       "tcpConnEntry", 1, 0,
+       &_tcpConnRemPort_obj, NULL
+},
+_tcpRtoAlgorithm_obj = {
+       "tcpRtoAlgorithm", 1, 0,
+       NULL, NULL
+},
+_tcpRtoMin_obj = {
+       "tcpRtoMin", 2, 0,
+       NULL, &_tcpRtoAlgorithm_obj
+},
+_tcpRtoMax_obj = {
+       "tcpRtoMax", 3, 0,
+       NULL, &_tcpRtoMin_obj
+},
+_tcpMaxConn_obj = {
+       "tcpMaxConn", 4, 0,
+       NULL, &_tcpRtoMax_obj
+},
+_tcpActiveOpens_obj = {
+       "tcpActiveOpens", 5, 0,
+       NULL, &_tcpMaxConn_obj
+},
+_tcpPassiveOpens_obj = {
+       "tcpPassiveOpens", 6, 0,
+       NULL, &_tcpActiveOpens_obj
+},
+_tcpAttemptFails_obj = {
+       "tcpAttemptFails", 7, 0,
+       NULL, &_tcpPassiveOpens_obj
+},
+_tcpEstabResets_obj = {
+       "tcpEstabResets", 8, 0,
+       NULL, &_tcpAttemptFails_obj
+},
+_tcpCurrEstab_obj = {
+       "tcpCurrEstab", 9, 0,
+       NULL, &_tcpEstabResets_obj
+},
+_tcpInSegs_obj = {
+       "tcpInSegs", 10, 0,
+       NULL, &_tcpCurrEstab_obj
+},
+_tcpOutSegs_obj = {
+       "tcpOutSegs", 11, 0,
+       NULL, &_tcpInSegs_obj
+},
+_tcpRetransSegs_obj = {
+       "tcpRetransSegs", 12, 0,
+       NULL, &_tcpOutSegs_obj
+},
+_tcpConnTable_obj = {
+       "tcpConnTable", 13, 0,
+       &_tcpConnEntry_obj, &_tcpRetransSegs_obj
+},
+_tcpInErrs_obj = {
+       "tcpInErrs", 14, 0,
+       NULL, &_tcpConnTable_obj
+},
+_tcpOutRsts_obj = {
+       "tcpOutRsts", 15, 0,
+       NULL, &_tcpInErrs_obj
+},
+_icmpInMsgs_obj = {
+       "icmpInMsgs", 1, 0,
+       NULL, NULL
+},
+_icmpInErrors_obj = {
+       "icmpInErrors", 2, 0,
+       NULL, &_icmpInMsgs_obj
+},
+_icmpInDestUnreachs_obj = {
+       "icmpInDestUnreachs", 3, 0,
+       NULL, &_icmpInErrors_obj
+},
+_icmpInTimeExcds_obj = {
+       "icmpInTimeExcds", 4, 0,
+       NULL, &_icmpInDestUnreachs_obj
+},
+_icmpInParmProbs_obj = {
+       "icmpInParmProbs", 5, 0,
+       NULL, &_icmpInTimeExcds_obj
+},
+_icmpInSrcQuenchs_obj = {
+       "icmpInSrcQuenchs", 6, 0,
+       NULL, &_icmpInParmProbs_obj
+},
+_icmpInRedirects_obj = {
+       "icmpInRedirects", 7, 0,
+       NULL, &_icmpInSrcQuenchs_obj
+},
+_icmpInEchos_obj = {
+       "icmpInEchos", 8, 0,
+       NULL, &_icmpInRedirects_obj
+},
+_icmpInEchoReps_obj = {
+       "icmpInEchoReps", 9, 0,
+       NULL, &_icmpInEchos_obj
+},
+_icmpInTimestamps_obj = {
+       "icmpInTimestamps", 10, 0,
+       NULL, &_icmpInEchoReps_obj
+},
+_icmpInTimestampReps_obj = {
+       "icmpInTimestampReps", 11, 0,
+       NULL, &_icmpInTimestamps_obj
+},
+_icmpInAddrMasks_obj = {
+       "icmpInAddrMasks", 12, 0,
+       NULL, &_icmpInTimestampReps_obj
+},
+_icmpInAddrMaskReps_obj = {
+       "icmpInAddrMaskReps", 13, 0,
+       NULL, &_icmpInAddrMasks_obj
+},
+_icmpOutMsgs_obj = {
+       "icmpOutMsgs", 14, 0,
+       NULL, &_icmpInAddrMaskReps_obj
+},
+_icmpOutErrors_obj = {
+       "icmpOutErrors", 15, 0,
+       NULL, &_icmpOutMsgs_obj
+},
+_icmpOutDestUnreachs_obj = {
+       "icmpOutDestUnreachs", 16, 0,
+       NULL, &_icmpOutErrors_obj
+},
+_icmpOutTimeExcds_obj = {
+       "icmpOutTimeExcds", 17, 0,
+       NULL, &_icmpOutDestUnreachs_obj
+},
+_icmpOutParmProbs_obj = {
+       "icmpOutParmProbs", 18, 0,
+       NULL, &_icmpOutTimeExcds_obj
+},
+_icmpOutSrcQuenchs_obj = {
+       "icmpOutSrcQuenchs", 19, 0,
+       NULL, &_icmpOutParmProbs_obj
+},
+_icmpOutRedirects_obj = {
+       "icmpOutRedirects", 20, 0,
+       NULL, &_icmpOutSrcQuenchs_obj
+},
+_icmpOutEchos_obj = {
+       "icmpOutEchos", 21, 0,
+       NULL, &_icmpOutRedirects_obj
+},
+_icmpOutEchoReps_obj = {
+       "icmpOutEchoReps", 22, 0,
+       NULL, &_icmpOutEchos_obj
+},
+_icmpOutTimestamps_obj = {
+       "icmpOutTimestamps", 23, 0,
+       NULL, &_icmpOutEchoReps_obj
+},
+_icmpOutTimestampReps_obj = {
+       "icmpOutTimestampReps", 24, 0,
+       NULL, &_icmpOutTimestamps_obj
+},
+_icmpOutAddrMasks_obj = {
+       "icmpOutAddrMasks", 25, 0,
+       NULL, &_icmpOutTimestampReps_obj
+},
+_icmpOutAddrMaskReps_obj = {
+       "icmpOutAddrMaskReps", 26, 0,
+       NULL, &_icmpOutAddrMasks_obj
+},
+_ipNetToMediaIfIndex_obj = {
+       "ipNetToMediaIfIndex", 1, 0,
+       NULL, NULL
+},
+_ipNetToMediaPhysAddress_obj = {
+       "ipNetToMediaPhysAddress", 2, 0,
+       NULL, &_ipNetToMediaIfIndex_obj
+},
+_ipNetToMediaNetAddress_obj = {
+       "ipNetToMediaNetAddress", 3, 0,
+       NULL, &_ipNetToMediaPhysAddress_obj
+},
+_ipNetToMediaType_obj = {
+       "ipNetToMediaType", 4, 0,
+       NULL, &_ipNetToMediaNetAddress_obj
+},
+_ipNetToMediaEntry_obj = {
+       "ipNetToMediaEntry", 1, 0,
+       &_ipNetToMediaType_obj, NULL
+},
+_ipRouteDest_obj = {
+       "ipRouteDest", 1, 0,
+       NULL, NULL
+},
+_ipRouteIfIndex_obj = {
+       "ipRouteIfIndex", 2, 0,
+       NULL, &_ipRouteDest_obj
+},
+_ipRouteMetric1_obj = {
+       "ipRouteMetric1", 3, 0,
+       NULL, &_ipRouteIfIndex_obj
+},
+_ipRouteMetric2_obj = {
+       "ipRouteMetric2", 4, 0,
+       NULL, &_ipRouteMetric1_obj
+},
+_ipRouteMetric3_obj = {
+       "ipRouteMetric3", 5, 0,
+       NULL, &_ipRouteMetric2_obj
+},
+_ipRouteMetric4_obj = {
+       "ipRouteMetric4", 6, 0,
+       NULL, &_ipRouteMetric3_obj
+},
+_ipRouteNextHop_obj = {
+       "ipRouteNextHop", 7, 0,
+       NULL, &_ipRouteMetric4_obj
+},
+_ipRouteType_obj = {
+       "ipRouteType", 8, 0,
+       NULL, &_ipRouteNextHop_obj
+},
+_ipRouteProto_obj = {
+       "ipRouteProto", 9, 0,
+       NULL, &_ipRouteType_obj
+},
+_ipRouteAge_obj = {
+       "ipRouteAge", 10, 0,
+       NULL, &_ipRouteProto_obj
+},
+_ipRouteMask_obj = {
+       "ipRouteMask", 11, 0,
+       NULL, &_ipRouteAge_obj
+},
+_ipRouteEntry_obj = {
+       "ipRouteEntry", 1, 0,
+       &_ipRouteMask_obj, NULL
+},
+_ipAdEntAddr_obj = {
+       "ipAdEntAddr", 1, 0,
+       NULL, NULL
+},
+_ipAdEntIfIndex_obj = {
+       "ipAdEntIfIndex", 2, 0,
+       NULL, &_ipAdEntAddr_obj
+},
+_ipAdEntNetMask_obj = {
+       "ipAdEntNetMask", 3, 0,
+       NULL, &_ipAdEntIfIndex_obj
+},
+_ipAdEntBcastAddr_obj = {
+       "ipAdEntBcastAddr", 4, 0,
+       NULL, &_ipAdEntNetMask_obj
+},
+_ipAdEntReasmMaxSize_obj = {
+       "ipAdEntReasmMaxSize", 5, 0,
+       NULL, &_ipAdEntBcastAddr_obj
+},
+_ipAddrEntry_obj = {
+       "ipAddrEntry", 1, 0,
+       &_ipAdEntReasmMaxSize_obj, NULL
+},
+_ipForwarding_obj = {
+       "ipForwarding", 1, 0,
+       NULL, NULL
+},
+_ipDefaultTTL_obj = {
+       "ipDefaultTTL", 2, 0,
+       NULL, &_ipForwarding_obj
+},
+_ipInReceives_obj = {
+       "ipInReceives", 3, 0,
+       NULL, &_ipDefaultTTL_obj
+},
+_ipInHdrErrors_obj = {
+       "ipInHdrErrors", 4, 0,
+       NULL, &_ipInReceives_obj
+},
+_ipInAddrErrors_obj = {
+       "ipInAddrErrors", 5, 0,
+       NULL, &_ipInHdrErrors_obj
+},
+_ipForwDatagrams_obj = {
+       "ipForwDatagrams", 6, 0,
+       NULL, &_ipInAddrErrors_obj
+},
+_ipInUnknownProtos_obj = {
+       "ipInUnknownProtos", 7, 0,
+       NULL, &_ipForwDatagrams_obj
+},
+_ipInDiscards_obj = {
+       "ipInDiscards", 8, 0,
+       NULL, &_ipInUnknownProtos_obj
+},
+_ipInDelivers_obj = {
+       "ipInDelivers", 9, 0,
+       NULL, &_ipInDiscards_obj
+},
+_ipOutRequests_obj = {
+       "ipOutRequests", 10, 0,
+       NULL, &_ipInDelivers_obj
+},
+_ipOutDiscards_obj = {
+       "ipOutDiscards", 11, 0,
+       NULL, &_ipOutRequests_obj
+},
+_ipOutNoRoutes_obj = {
+       "ipOutNoRoutes", 12, 0,
+       NULL, &_ipOutDiscards_obj
+},
+_ipReasmTimeout_obj = {
+       "ipReasmTimeout", 13, 0,
+       NULL, &_ipOutNoRoutes_obj
+},
+_ipReasmReqds_obj = {
+       "ipReasmReqds", 14, 0,
+       NULL, &_ipReasmTimeout_obj
+},
+_ipReasmOKs_obj = {
+       "ipReasmOKs", 15, 0,
+       NULL, &_ipReasmReqds_obj
+},
+_ipReasmFails_obj = {
+       "ipReasmFails", 16, 0,
+       NULL, &_ipReasmOKs_obj
+},
+_ipFragOKs_obj = {
+       "ipFragOKs", 17, 0,
+       NULL, &_ipReasmFails_obj
+},
+_ipFragFails_obj = {
+       "ipFragFails", 18, 0,
+       NULL, &_ipFragOKs_obj
+},
+_ipFragCreates_obj = {
+       "ipFragCreates", 19, 0,
+       NULL, &_ipFragFails_obj
+},
+_ipAddrTable_obj = {
+       "ipAddrTable", 20, 0,
+       &_ipAddrEntry_obj, &_ipFragCreates_obj
+},
+_ipRoutingTable_obj = {
+       "ipRoutingTable", 21, 0,
+       &_ipRouteEntry_obj, &_ipAddrTable_obj
+},
+_ipNetToMediaTable_obj = {
+       "ipNetToMediaTable", 22, 0,
+       &_ipNetToMediaEntry_obj, &_ipRoutingTable_obj
+},
+_atIfIndex_obj = {
+       "atIfIndex", 1, 0,
+       NULL, NULL
+},
+_atPhysAddress_obj = {
+       "atPhysAddress", 2, 0,
+       NULL, &_atIfIndex_obj
+},
+_atNetAddress_obj = {
+       "atNetAddress", 3, 0,
+       NULL, &_atPhysAddress_obj
+},
+_atEntry_obj = {
+       "atEntry", 1, 0,
+       &_atNetAddress_obj, NULL
+},
+_atTable_obj = {
+       "atTable", 1, 0,
+       &_atEntry_obj, NULL
+},
+_ifIndex_obj = {
+       "ifIndex", 1, 0,
+       NULL, NULL
+},
+_ifDescr_obj = {
+       "ifDescr", 2, 0,
+       NULL, &_ifIndex_obj
+},
+_ifType_obj = {
+       "ifType", 3, 0,
+       NULL, &_ifDescr_obj
+},
+_ifMtu_obj = {
+       "ifMtu", 4, 0,
+       NULL, &_ifType_obj
+},
+_ifSpeed_obj = {
+       "ifSpeed", 5, 0,
+       NULL, &_ifMtu_obj
+},
+_ifPhysAddress_obj = {
+       "ifPhysAddress", 6, 0,
+       NULL, &_ifSpeed_obj
+},
+_ifAdminStatus_obj = {
+       "ifAdminStatus", 7, 0,
+       NULL, &_ifPhysAddress_obj
+},
+_ifOperStatus_obj = {
+       "ifOperStatus", 8, 0,
+       NULL, &_ifAdminStatus_obj
+},
+_ifLastChange_obj = {
+       "ifLastChange", 9, 0,
+       NULL, &_ifOperStatus_obj
+},
+_ifInOctets_obj = {
+       "ifInOctets", 10, 0,
+       NULL, &_ifLastChange_obj
+},
+_ifInUcastPkts_obj = {
+       "ifInUcastPkts", 11, 0,
+       NULL, &_ifInOctets_obj
+},
+_ifInNUcastPkts_obj = {
+       "ifInNUcastPkts", 12, 0,
+       NULL, &_ifInUcastPkts_obj
+},
+_ifInDiscards_obj = {
+       "ifInDiscards", 13, 0,
+       NULL, &_ifInNUcastPkts_obj
+},
+_ifInErrors_obj = {
+       "ifInErrors", 14, 0,
+       NULL, &_ifInDiscards_obj
+},
+_ifInUnknownProtos_obj = {
+       "ifInUnknownProtos", 15, 0,
+       NULL, &_ifInErrors_obj
+},
+_ifOutOctets_obj = {
+       "ifOutOctets", 16, 0,
+       NULL, &_ifInUnknownProtos_obj
+},
+_ifOutUcastPkts_obj = {
+       "ifOutUcastPkts", 17, 0,
+       NULL, &_ifOutOctets_obj
+},
+_ifOutNUcastPkts_obj = {
+       "ifOutNUcastPkts", 18, 0,
+       NULL, &_ifOutUcastPkts_obj
+},
+_ifOutDiscards_obj = {
+       "ifOutDiscards", 19, 0,
+       NULL, &_ifOutNUcastPkts_obj
+},
+_ifOutErrors_obj = {
+       "ifOutErrors", 20, 0,
+       NULL, &_ifOutDiscards_obj
+},
+_ifOutQLen_obj = {
+       "ifOutQLen", 21, 0,
+       NULL, &_ifOutErrors_obj
+},
+_ifSpecific_obj = {
+       "ifSpecific", 22, 0,
+       NULL, &_ifOutQLen_obj
+},
+_ifEntry_obj = {
+       "ifEntry", 1, 0,
+       &_ifSpecific_obj, NULL
+},
+_ifNumber_obj = {
+       "ifNumber", 1, 0,
+       NULL, NULL
+},
+_ifTable_obj = {
+       "ifTable", 2, 0,
+       &_ifEntry_obj, &_ifNumber_obj
+},
+_sysDescr_obj = {
+       "sysDescr", 1, 0,
+       NULL, NULL
+},
+_sysObjectID_obj = {
+       "sysObjectID", 2, 0,
+       NULL, &_sysDescr_obj
+},
+_sysUpTime_obj = {
+       "sysUpTime", 3, 0,
+       NULL, &_sysObjectID_obj
+},
+_sysContact_obj = {
+       "sysContact", 4, 0,
+       NULL, &_sysUpTime_obj
+},
+_sysName_obj = {
+       "sysName", 5, 0,
+       NULL, &_sysContact_obj
+},
+_sysLocation_obj = {
+       "sysLocation", 6, 0,
+       NULL, &_sysName_obj
+},
+_sysServices_obj = {
+       "sysServices", 7, 0,
+       NULL, &_sysLocation_obj
+},
+_system_obj = {
+       "system", 1, 0,
+       &_sysServices_obj, NULL
+},
+_interfaces_obj = {
+       "interfaces", 2, 0,
+       &_ifTable_obj, &_system_obj
+},
+_at_obj = {
+       "at", 3, 0,
+       &_atTable_obj, &_interfaces_obj
+},
+_ip_obj = {
+       "ip", 4, 0,
+       &_ipNetToMediaTable_obj, &_at_obj
+},
+_icmp_obj = {
+       "icmp", 5, 0,
+       &_icmpOutAddrMaskReps_obj, &_ip_obj
+},
+_tcp_obj = {
+       "tcp", 6, 0,
+       &_tcpOutRsts_obj, &_icmp_obj
+},
+_udp_obj = {
+       "udp", 7, 0,
+       &_udpTable_obj, &_tcp_obj
+},
+_egp_obj = {
+       "egp", 8, 0,
+       &_egpAs_obj, &_udp_obj
+},
+_transmission_obj = {
+       "transmission", 10, 0,
+       NULL, &_egp_obj
+},
+_snmp_obj = {
+       "snmp", 11, 0,
+       &_snmpEnableAuthTraps_obj, &_transmission_obj
+},
+_mib_obj = {
+       "mib", 1, 0,
+       &_snmp_obj, NULL
+},
+_directory_obj = {
+       "directory", 1, 0,
+       NULL, NULL
+},
+_mgmt_obj = {
+       "mgmt", 2, 0,
+       &_mib_obj, &_directory_obj
+},
+_experimental_obj = {
+       "experimental", 3, 0,
+       NULL, &_mgmt_obj
+},
+_private_obj = {
+       "private", 4, 0,
+       &_enterprises_obj, &_experimental_obj
+},
+_internet_obj = {
+       "internet", 1, 0,
+       &_private_obj, NULL
+},
+_dod_obj = {
+       "dod", 6, 0,
+       &_internet_obj, NULL
+},
+_org_obj = {
+       "org", 3, 0,
+       &_dod_obj, NULL
+},
+_iso_obj = {
+       "iso", 1, 0,
+       &_org_obj, NULL
+},
+*mibroot = &_iso_obj;
diff --git a/tcpdump.tproj/netbios.h b/tcpdump.tproj/netbios.h
new file mode 100644 (file)
index 0000000..629e5a5
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * NETBIOS protocol formats
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/netbios.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $
+ */
+
+struct p8022Hdr {
+    u_char     dsap;
+    u_char     ssap;
+    u_char     flags;
+};
+
+#define        p8022Size       3               /* min 802.2 header size */
+
+#define UI             0x03            /* 802.2 flags */
+
diff --git a/tcpdump.tproj/nfs.h b/tcpdump.tproj/nfs.h
new file mode 100644 (file)
index 0000000..a45e1ce
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: nfs.h,v 1.2 1996/07/13 11:01:12 mickey Exp $  */
+/*     $NetBSD: nfs.h,v 1.1 1996/05/23 22:49:53 fvdl Exp $     */
+
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)nfsproto.h  8.2 (Berkeley) 3/30/95
+ */
+
+/*
+ * nfs definitions as per the Version 2 and 3 specs
+ */
+
+/*
+ * Constants as defined in the Sun NFS Version 2 and 3 specs.
+ * "NFS: Network File System Protocol Specification" RFC1094
+ * and in the "NFS: Network File System Version 3 Protocol
+ * Specification"
+ */
+
+#define NFS_PORT       2049
+#define        NFS_PROG        100003
+#define NFS_VER2       2
+#define        NFS_VER3        3
+#define NFS_V2MAXDATA  8192
+#define        NFS_MAXDGRAMDATA 16384
+#define        NFS_MAXDATA     32768
+#define        NFS_MAXPATHLEN  1024
+#define        NFS_MAXNAMLEN   255
+#define        NFS_MAXPKTHDR   404
+#define NFS_MAXPACKET  (NFS_MAXPKTHDR + NFS_MAXDATA)
+#define        NFS_MINPACKET   20
+#define        NFS_FABLKSIZE   512     /* Size in bytes of a block wrt fa_blocks */
+
+/* Stat numbers for rpc returns (version 2 and 3) */
+#define        NFS_OK                  0
+#define        NFSERR_PERM             1
+#define        NFSERR_NOENT            2
+#define        NFSERR_IO               5
+#define        NFSERR_NXIO             6
+#define        NFSERR_ACCES            13
+#define        NFSERR_EXIST            17
+#define        NFSERR_XDEV             18      /* Version 3 only */
+#define        NFSERR_NODEV            19
+#define        NFSERR_NOTDIR           20
+#define        NFSERR_ISDIR            21
+#define        NFSERR_INVAL            22      /* Version 3 only */
+#define        NFSERR_FBIG             27
+#define        NFSERR_NOSPC            28
+#define        NFSERR_ROFS             30
+#define        NFSERR_MLINK            31      /* Version 3 only */
+#define        NFSERR_NAMETOL          63
+#define        NFSERR_NOTEMPTY         66
+#define        NFSERR_DQUOT            69
+#define        NFSERR_STALE            70
+#define        NFSERR_REMOTE           71      /* Version 3 only */
+#define        NFSERR_WFLUSH           99      /* Version 2 only */
+#define        NFSERR_BADHANDLE        10001   /* The rest Version 3 only */
+#define        NFSERR_NOT_SYNC         10002
+#define        NFSERR_BAD_COOKIE       10003
+#define        NFSERR_NOTSUPP          10004
+#define        NFSERR_TOOSMALL         10005
+#define        NFSERR_SERVERFAULT      10006
+#define        NFSERR_BADTYPE          10007
+#define        NFSERR_JUKEBOX          10008
+#define NFSERR_TRYLATER                NFSERR_JUKEBOX
+#define        NFSERR_STALEWRITEVERF   30001   /* Fake return for nfs_commit() */
+
+#define NFSERR_RETVOID         0x20000000 /* Return void, not error */
+#define NFSERR_AUTHERR         0x40000000 /* Mark an authentication error */
+#define NFSERR_RETERR          0x80000000 /* Mark an error return for V3 */
+
+/* Sizes in bytes of various nfs rpc components */
+#define        NFSX_UNSIGNED   4
+
+/* specific to NFS Version 2 */
+#define        NFSX_V2FH       32
+#define        NFSX_V2FATTR    68
+#define        NFSX_V2SATTR    32
+#define        NFSX_V2COOKIE   4
+#define NFSX_V2STATFS  20
+
+/* specific to NFS Version 3 */
+#if 0
+#define NFSX_V3FH              (sizeof (fhandle_t)) /* size this server uses */
+#endif
+#define        NFSX_V3FHMAX            64      /* max. allowed by protocol */
+#define NFSX_V3FATTR           84
+#define NFSX_V3SATTR           60      /* max. all fields filled in */
+#define NFSX_V3SRVSATTR                (sizeof (struct nfsv3_sattr))
+#define NFSX_V3POSTOPATTR      (NFSX_V3FATTR + NFSX_UNSIGNED)
+#define NFSX_V3WCCDATA         (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
+#define NFSX_V3COOKIEVERF      8
+#define NFSX_V3WRITEVERF       8
+#define NFSX_V3CREATEVERF      8
+#define NFSX_V3STATFS          52
+#define NFSX_V3FSINFO          48
+#define NFSX_V3PATHCONF                24
+
+/* variants for both versions */
+#define NFSX_FH(v3)            ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
+                                       NFSX_V2FH)
+#define NFSX_SRVFH(v3)         ((v3) ? NFSX_V3FH : NFSX_V2FH)
+#define        NFSX_FATTR(v3)          ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
+#define NFSX_PREOPATTR(v3)     ((v3) ? (7 * NFSX_UNSIGNED) : 0)
+#define NFSX_POSTOPATTR(v3)    ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
+#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
+                                       NFSX_V2FATTR)
+#define NFSX_WCCDATA(v3)       ((v3) ? NFSX_V3WCCDATA : 0)
+#define NFSX_WCCORFATTR(v3)    ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR)
+#define        NFSX_SATTR(v3)          ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
+#define        NFSX_COOKIEVERF(v3)     ((v3) ? NFSX_V3COOKIEVERF : 0)
+#define        NFSX_WRITEVERF(v3)      ((v3) ? NFSX_V3WRITEVERF : 0)
+#define NFSX_READDIR(v3)       ((v3) ? (5 * NFSX_UNSIGNED) : \
+                                       (2 * NFSX_UNSIGNED))
+#define        NFSX_STATFS(v3)         ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS)
+
+/* nfs rpc procedure numbers (before version mapping) */
+#define        NFSPROC_NULL            0
+#define        NFSPROC_GETATTR         1
+#define        NFSPROC_SETATTR         2
+#define        NFSPROC_LOOKUP          3
+#define        NFSPROC_ACCESS          4
+#define        NFSPROC_READLINK        5
+#define        NFSPROC_READ            6
+#define        NFSPROC_WRITE           7
+#define        NFSPROC_CREATE          8
+#define        NFSPROC_MKDIR           9
+#define        NFSPROC_SYMLINK         10
+#define        NFSPROC_MKNOD           11
+#define        NFSPROC_REMOVE          12
+#define        NFSPROC_RMDIR           13
+#define        NFSPROC_RENAME          14
+#define        NFSPROC_LINK            15
+#define        NFSPROC_READDIR         16
+#define        NFSPROC_READDIRPLUS     17
+#define        NFSPROC_FSSTAT          18
+#define        NFSPROC_FSINFO          19
+#define        NFSPROC_PATHCONF        20
+#define        NFSPROC_COMMIT          21
+
+/* And leasing (nqnfs) procedure numbers (must be last) */
+#define        NQNFSPROC_GETLEASE      22
+#define        NQNFSPROC_VACATED       23
+#define        NQNFSPROC_EVICTED       24
+
+#define NFSPROC_NOOP           25
+#define        NFS_NPROCS              26
+
+/* Actual Version 2 procedure numbers */
+#define        NFSV2PROC_NULL          0
+#define        NFSV2PROC_GETATTR       1
+#define        NFSV2PROC_SETATTR       2
+#define        NFSV2PROC_NOOP          3
+#define        NFSV2PROC_ROOT          NFSV2PROC_NOOP  /* Obsolete */
+#define        NFSV2PROC_LOOKUP        4
+#define        NFSV2PROC_READLINK      5
+#define        NFSV2PROC_READ          6
+#define        NFSV2PROC_WRITECACHE    NFSV2PROC_NOOP  /* Obsolete */
+#define        NFSV2PROC_WRITE         8
+#define        NFSV2PROC_CREATE        9
+#define        NFSV2PROC_REMOVE        10
+#define        NFSV2PROC_RENAME        11
+#define        NFSV2PROC_LINK          12
+#define        NFSV2PROC_SYMLINK       13
+#define        NFSV2PROC_MKDIR         14
+#define        NFSV2PROC_RMDIR         15
+#define        NFSV2PROC_READDIR       16
+#define        NFSV2PROC_STATFS        17
+
+/*
+ * Constants used by the Version 3 protocol for various RPCs
+ */
+#define NFSV3SATTRTIME_DONTCHANGE      0
+#define NFSV3SATTRTIME_TOSERVER                1
+#define NFSV3SATTRTIME_TOCLIENT                2
+
+#define NFSV3ATTRTIME_NMODES           3
+
+#define NFSV3ACCESS_READ               0x01
+#define NFSV3ACCESS_LOOKUP             0x02
+#define NFSV3ACCESS_MODIFY             0x04
+#define NFSV3ACCESS_EXTEND             0x08
+#define NFSV3ACCESS_DELETE             0x10
+#define NFSV3ACCESS_EXECUTE            0x20
+
+#define NFSV3WRITE_UNSTABLE            0
+#define NFSV3WRITE_DATASYNC            1
+#define NFSV3WRITE_FILESYNC            2
+
+#define NFSV3WRITE_NMODES              3
+
+#define NFSV3CREATE_UNCHECKED          0
+#define NFSV3CREATE_GUARDED            1
+#define NFSV3CREATE_EXCLUSIVE          2
+
+#define NFSV3CREATE_NMODES             3
+
+#define NFSV3FSINFO_LINK               0x01
+#define NFSV3FSINFO_SYMLINK            0x02
+#define NFSV3FSINFO_HOMOGENEOUS                0x08
+#define NFSV3FSINFO_CANSETTIME         0x10
+
+/* Conversion macros */
+#define        vtonfsv2_mode(t,m) \
+               txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
+                               MAKEIMODE((t), (m)))
+#define vtonfsv3_mode(m)       txdr_unsigned((m) & 07777)
+#define        nfstov_mode(a)          (fxdr_unsigned(u_int16_t, (a))&07777)
+#define        vtonfsv2_type(a)        txdr_unsigned(nfsv2_type[((int32_t)(a))])
+#define        vtonfsv3_type(a)        txdr_unsigned(nfsv3_type[((int32_t)(a))])
+#define        nfsv2tov_type(a)        nv2tov_type[fxdr_unsigned(u_int32,(a))&0x7]
+#define        nfsv3tov_type(a)        nv3tov_type[fxdr_unsigned(u_int32,(a))&0x7]
+
+/* File types */
+typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
+       NFSOCK=6, NFFIFO=7 } nfstype;
+
+/* Structs for common parts of the rpc's */
+/*
+ * File Handle (32 bytes for version 2), variable up to 64 for version 3.
+ * File Handles of up to NFS_SMALLFH in size are stored directly in the
+ * nfs node, whereas larger ones are malloc'd. (This never happens when
+ * NFS_SMALLFH is set to 64.)
+ * NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
+ */
+#ifndef NFS_SMALLFH
+#define NFS_SMALLFH    64
+#endif
+union nfsfh {
+/*     fhandle_t fh_generic; */
+       u_char    fh_bytes[NFS_SMALLFH];
+};
+typedef union nfsfh nfsfh_t;
+
+struct nfsv2_time {
+       u_int32 nfsv2_sec;
+       u_int32 nfsv2_usec;
+};
+typedef struct nfsv2_time      nfstime2;
+
+struct nfsv3_time {
+       u_int32 nfsv3_sec;
+       u_int32 nfsv3_nsec;
+};
+typedef struct nfsv3_time      nfstime3;
+
+/*
+ * Quads are defined as arrays of 2 longs to ensure dense packing for the
+ * protocol and to facilitate xdr conversion.
+ */
+struct nfs_uquad {
+       u_int32 nfsuquad[2];
+};
+typedef        struct nfs_uquad        nfsuint64;
+
+/*
+ * Used to convert between two u_longs and a u_quad_t.
+ */
+union nfs_quadconvert {
+       u_int32 lval[2];
+       u_quad_t  qval;
+};
+typedef union nfs_quadconvert  nfsquad_t;
+
+/*
+ * NFS Version 3 special file number.
+ */
+struct nfsv3_spec {
+       u_int32 specdata1;
+       u_int32 specdata2;
+};
+typedef        struct nfsv3_spec       nfsv3spec;
+
+/*
+ * File attributes and setable attributes. These structures cover both
+ * NFS version 2 and the version 3 protocol. Note that the union is only
+ * used so that one pointer can refer to both variants. These structures
+ * go out on the wire and must be densely packed, so no quad data types
+ * are used. (all fields are longs or u_longs or structures of same)
+ * NB: You can't do sizeof(struct nfs_fattr), you must use the
+ *     NFSX_FATTR(v3) macro.
+ */
+struct nfs_fattr {
+       u_int32 fa_type;
+       u_int32 fa_mode;
+       u_int32 fa_nlink;
+       u_int32 fa_uid;
+       u_int32 fa_gid;
+       union {
+               struct {
+                       u_int32 nfsv2fa_size;
+                       u_int32 nfsv2fa_blocksize;
+                       u_int32 nfsv2fa_rdev;
+                       u_int32 nfsv2fa_blocks;
+                       u_int32 nfsv2fa_fsid;
+                       u_int32 nfsv2fa_fileid;
+                       nfstime2  nfsv2fa_atime;
+                       nfstime2  nfsv2fa_mtime;
+                       nfstime2  nfsv2fa_ctime;
+               } fa_nfsv2;
+               struct {
+                       nfsuint64 nfsv3fa_size;
+                       nfsuint64 nfsv3fa_used;
+                       nfsv3spec nfsv3fa_rdev;
+                       nfsuint64 nfsv3fa_fsid;
+                       nfsuint64 nfsv3fa_fileid;
+                       nfstime3  nfsv3fa_atime;
+                       nfstime3  nfsv3fa_mtime;
+                       nfstime3  nfsv3fa_ctime;
+               } fa_nfsv3;
+       } fa_un;
+};
+
+/* and some ugly defines for accessing union components */
+#define        fa2_size                fa_un.fa_nfsv2.nfsv2fa_size
+#define        fa2_blocksize           fa_un.fa_nfsv2.nfsv2fa_blocksize
+#define        fa2_rdev                fa_un.fa_nfsv2.nfsv2fa_rdev
+#define        fa2_blocks              fa_un.fa_nfsv2.nfsv2fa_blocks
+#define        fa2_fsid                fa_un.fa_nfsv2.nfsv2fa_fsid
+#define        fa2_fileid              fa_un.fa_nfsv2.nfsv2fa_fileid
+#define        fa2_atime               fa_un.fa_nfsv2.nfsv2fa_atime
+#define        fa2_mtime               fa_un.fa_nfsv2.nfsv2fa_mtime
+#define        fa2_ctime               fa_un.fa_nfsv2.nfsv2fa_ctime
+#define        fa3_size                fa_un.fa_nfsv3.nfsv3fa_size
+#define        fa3_used                fa_un.fa_nfsv3.nfsv3fa_used
+#define        fa3_rdev                fa_un.fa_nfsv3.nfsv3fa_rdev
+#define        fa3_fsid                fa_un.fa_nfsv3.nfsv3fa_fsid
+#define        fa3_fileid              fa_un.fa_nfsv3.nfsv3fa_fileid
+#define        fa3_atime               fa_un.fa_nfsv3.nfsv3fa_atime
+#define        fa3_mtime               fa_un.fa_nfsv3.nfsv3fa_mtime
+#define        fa3_ctime               fa_un.fa_nfsv3.nfsv3fa_ctime
+
+struct nfsv2_sattr {
+       u_int32 sa_mode;
+       u_int32 sa_uid;
+       u_int32 sa_gid;
+       u_int32 sa_size;
+       nfstime2  sa_atime;
+       nfstime2  sa_mtime;
+};
+
+/*
+ * NFS Version 3 sattr structure for the new node creation case.
+ */
+struct nfsv3_sattr {
+       u_int32   sa_modeset;
+       u_int32   sa_mode;
+       u_int32   sa_uidset;
+       u_int32   sa_uid;
+       u_int32   sa_gidset;
+       u_int32   sa_gid;
+       u_int32   sa_sizeset;
+       u_int32   sa_size;
+       u_int32   sa_atimetype;
+       nfstime3  sa_atime;
+       u_int32   sa_mtimetype;
+       nfstime3  sa_mtime;
+};
+
+struct nfs_statfs {
+       union {
+               struct {
+                       u_int32 nfsv2sf_tsize;
+                       u_int32 nfsv2sf_bsize;
+                       u_int32 nfsv2sf_blocks;
+                       u_int32 nfsv2sf_bfree;
+                       u_int32 nfsv2sf_bavail;
+               } sf_nfsv2;
+               struct {
+                       nfsuint64 nfsv3sf_tbytes;
+                       nfsuint64 nfsv3sf_fbytes;
+                       nfsuint64 nfsv3sf_abytes;
+                       nfsuint64 nfsv3sf_tfiles;
+                       nfsuint64 nfsv3sf_ffiles;
+                       nfsuint64 nfsv3sf_afiles;
+                       u_int32 nfsv3sf_invarsec;
+               } sf_nfsv3;
+       } sf_un;
+};
+
+#define sf_tsize       sf_un.sf_nfsv2.nfsv2sf_tsize
+#define sf_bsize       sf_un.sf_nfsv2.nfsv2sf_bsize
+#define sf_blocks      sf_un.sf_nfsv2.nfsv2sf_blocks
+#define sf_bfree       sf_un.sf_nfsv2.nfsv2sf_bfree
+#define sf_bavail      sf_un.sf_nfsv2.nfsv2sf_bavail
+#define sf_tbytes      sf_un.sf_nfsv3.nfsv3sf_tbytes
+#define sf_fbytes      sf_un.sf_nfsv3.nfsv3sf_fbytes
+#define sf_abytes      sf_un.sf_nfsv3.nfsv3sf_abytes
+#define sf_tfiles      sf_un.sf_nfsv3.nfsv3sf_tfiles
+#define sf_ffiles      sf_un.sf_nfsv3.nfsv3sf_ffiles
+#define sf_afiles      sf_un.sf_nfsv3.nfsv3sf_afiles
+#define sf_invarsec    sf_un.sf_nfsv3.nfsv3sf_invarsec
+
+struct nfsv3_fsinfo {
+       u_int32 fs_rtmax;
+       u_int32 fs_rtpref;
+       u_int32 fs_rtmult;
+       u_int32 fs_wtmax;
+       u_int32 fs_wtpref;
+       u_int32 fs_wtmult;
+       u_int32 fs_dtpref;
+       nfsuint64 fs_maxfilesize;
+       nfstime3  fs_timedelta;
+       u_int32 fs_properties;
+};
+
+struct nfsv3_pathconf {
+       u_int32 pc_linkmax;
+       u_int32 pc_namemax;
+       u_int32 pc_notrunc;
+       u_int32 pc_chownrestricted;
+       u_int32 pc_caseinsensitive;
+       u_int32 pc_casepreserving;
+};
diff --git a/tcpdump.tproj/nfsfh.h b/tcpdump.tproj/nfsfh.h
new file mode 100644 (file)
index 0000000..f354eec
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/nfsfh.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $
+ *
+ * nfsfh.h - NFS file handle definitions (for portable use)
+ *
+ * Jeffrey C. Mogul
+ * Digital Equipment Corporation
+ * Western Research Laboratory
+ */
+
+/*
+ * Internal representation of dev_t, because different NFS servers
+ * that we might be spying upon use different external representations.
+ */
+typedef struct {
+       u_int32_t Minor;        /* upper case to avoid clashing with macro names */
+       u_int32_t Major;
+} my_devt;
+
+#define        dev_eq(a,b)     ((a.Minor == b.Minor) && (a.Major == b.Major))
+
+/*
+ * Many file servers now use a large file system ID.  This is
+ * our internal representation of that.
+ */
+typedef        struct {
+       my_devt Fsid_dev;               /* XXX avoid name conflict with AIX */
+       u_int32_t fsid_code;
+} my_fsid;
+
+#define        fsid_eq(a,b)    ((a.fsid_code == b.fsid_code) &&\
+                        dev_eq(a.fsid_dev, b.fsid_dev))
+
+extern void Parse_fh(caddr_t *, my_fsid *, ino_t *, char **, char **, int);
diff --git a/tcpdump.tproj/nfsv2.h b/tcpdump.tproj/nfsv2.h
new file mode 100644 (file)
index 0000000..d991ddc
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)nfsv2.h     7.11 (Berkeley) 9/30/92
+ */
+
+/*
+ * nfs definitions as per the version 2 specs
+ */
+
+/*
+ * Constants as defined in the Sun NFS Version 2 spec.
+ * "NFS: Network File System Protocol Specification" RFC1094
+ */
+
+#define NFS_PORT       2049
+#define        NFS_PROG        100003
+#define NFS_VER2       2
+#define        NFS_MAXDGRAMDATA 8192
+#define        NFS_MAXDATA     32768
+#define        NFS_MAXPATHLEN  1024
+#define        NFS_MAXNAMLEN   255
+#define        NFS_FHSIZE      32
+#define        NFS_MAXPKTHDR   404
+#define NFS_MAXPACKET  (NFS_MAXPKTHDR+NFS_MAXDATA)
+#define        NFS_MINPACKET   20
+#define        NFS_FABLKSIZE   512     /* Size in bytes of a block wrt fa_blocks */
+
+/* Stat numbers for rpc returns */
+#define        NFS_OK          0
+#define        NFSERR_PERM     1
+#define        NFSERR_NOENT    2
+#define        NFSERR_IO       5
+#define        NFSERR_NXIO     6
+#define        NFSERR_ACCES    13
+#define        NFSERR_EXIST    17
+#define        NFSERR_NODEV    19
+#define        NFSERR_NOTDIR   20
+#define        NFSERR_ISDIR    21
+#define        NFSERR_FBIG     27
+#define        NFSERR_NOSPC    28
+#define        NFSERR_ROFS     30
+#define        NFSERR_NAMETOL  63
+#define        NFSERR_NOTEMPTY 66
+#define        NFSERR_DQUOT    69
+#define        NFSERR_STALE    70
+#define        NFSERR_WFLUSH   99
+
+/* Sizes in bytes of various nfs rpc components */
+#define        NFSX_FH         32
+#define        NFSX_UNSIGNED   4
+#define        NFSX_NFSFATTR   68
+#define        NFSX_NQFATTR    92
+#define        NFSX_NFSSATTR   32
+#define        NFSX_NQSATTR    44
+#define        NFSX_COOKIE     4
+#define NFSX_NFSSTATFS 20
+#define        NFSX_NQSTATFS   28
+#define        NFSX_FATTR(isnq)        ((isnq) ? NFSX_NQFATTR : NFSX_NFSFATTR)
+#define        NFSX_SATTR(isnq)        ((isnq) ? NFSX_NQSATTR : NFSX_NFSSATTR)
+#define        NFSX_STATFS(isnq)       ((isnq) ? NFSX_NQSTATFS : NFSX_NFSSTATFS)
+
+/* nfs rpc procedure numbers */
+#define        NFSPROC_NULL            0
+#define        NFSPROC_GETATTR         1
+#define        NFSPROC_SETATTR         2
+#define        NFSPROC_NOOP            3
+#define        NFSPROC_ROOT            NFSPROC_NOOP    /* Obsolete */
+#define        NFSPROC_LOOKUP          4
+#define        NFSPROC_READLINK        5
+#define        NFSPROC_READ            6
+#define        NFSPROC_WRITECACHE      NFSPROC_NOOP    /* Obsolete */
+#define        NFSPROC_WRITE           8
+#define        NFSPROC_CREATE          9
+#define        NFSPROC_REMOVE          10
+#define        NFSPROC_RENAME          11
+#define        NFSPROC_LINK            12
+#define        NFSPROC_SYMLINK         13
+#define        NFSPROC_MKDIR           14
+#define        NFSPROC_RMDIR           15
+#define        NFSPROC_READDIR         16
+#define        NFSPROC_STATFS          17
+
+/* NQ nfs numbers */
+#define        NQNFSPROC_READDIRLOOK   18
+#define        NQNFSPROC_GETLEASE      19
+#define        NQNFSPROC_VACATED       20
+#define        NQNFSPROC_EVICTED       21
+#define        NQNFSPROC_ACCESS        22
+
+#define        NFS_NPROCS              23
+/* Conversion macros */
+extern int             vttoif_tab[];
+#define        vtonfs_mode(t,m) \
+               txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
+                               MAKEIMODE((t), (m)))
+#define        nfstov_mode(a)  (fxdr_unsigned(u_short, (a))&07777)
+#define        vtonfs_type(a)  txdr_unsigned(nfs_type[((int32_t)(a))])
+#define        nfstov_type(a)  ntov_type[fxdr_unsigned(u_int32_t,(a))&0x7]
+
+/* File types */
+typedef enum {
+    NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5
+} tcpdump_nfstype;
+
+/* Structs for common parts of the rpc's */
+struct nfsv2_time {
+       u_int32_t nfs_sec;
+       u_int32_t nfs_usec;
+};
+
+struct nqnfs_time {
+       u_int32_t nq_sec;
+       u_int32_t nq_nsec;
+};
+
+/*
+ * File attributes and setable attributes. These structures cover both
+ * NFS version 2 and the NQNFS protocol. Note that the union is only
+ * used to that one pointer can refer to both variants. These structures
+ * go out on the wire and must be densely packed, so no quad data types
+ * are used. (all fields are int32_t or u_int32_t's or structures of same)
+ * NB: You can't do sizeof(struct nfsv2_fattr), you must use the
+ *     NFSX_FATTR(isnq) macro.
+ */
+struct nfsv2_fattr {
+       u_int32_t fa_type;
+       u_int32_t fa_mode;
+       u_int32_t fa_nlink;
+       u_int32_t fa_uid;
+       u_int32_t fa_gid;
+       union {
+               struct {
+                       u_int32_t nfsfa_size;
+                       u_int32_t nfsfa_blocksize;
+                       u_int32_t nfsfa_rdev;
+                       u_int32_t nfsfa_blocks;
+                       u_int32_t nfsfa_fsid;
+                       u_int32_t nfsfa_fileid;
+                       struct nfsv2_time nfsfa_atime;
+                       struct nfsv2_time nfsfa_mtime;
+                       struct nfsv2_time nfsfa_ctime;
+               } fa_nfsv2;
+               struct {
+                       struct {
+                               u_int32_t nqfa_qsize[2];
+                       } nqfa_size;
+                       u_int32_t nqfa_blocksize;
+                       u_int32_t nqfa_rdev;
+                       struct {
+                               u_int32_t       nqfa_qbytes[2];
+                       } nqfa_bytes;
+                       u_int32_t nqfa_fsid;
+                       u_int32_t nqfa_fileid;
+                       struct nqnfs_time nqfa_atime;
+                       struct nqnfs_time nqfa_mtime;
+                       struct nqnfs_time nqfa_ctime;
+                       u_int32_t nqfa_flags;
+                       u_int32_t nqfa_gen;
+                       struct {
+                               u_int32_t nqfa_qfilerev[2];
+                       } nqfa_filerev;
+               } fa_nqnfs;
+       } fa_un;
+};
+
+/* and some ugly defines for accessing union components */
+#define        fa_nfssize              fa_un.fa_nfsv2.nfsfa_size
+#define        fa_nfsblocksize         fa_un.fa_nfsv2.nfsfa_blocksize
+#define        fa_nfsrdev              fa_un.fa_nfsv2.nfsfa_rdev
+#define        fa_nfsblocks            fa_un.fa_nfsv2.nfsfa_blocks
+#define        fa_nfsfsid              fa_un.fa_nfsv2.nfsfa_fsid
+#define        fa_nfsfileid            fa_un.fa_nfsv2.nfsfa_fileid
+#define        fa_nfsatime             fa_un.fa_nfsv2.nfsfa_atime
+#define        fa_nfsmtime             fa_un.fa_nfsv2.nfsfa_mtime
+#define        fa_nfsctime             fa_un.fa_nfsv2.nfsfa_ctime
+#define        fa_nqsize               fa_un.fa_nqnfs.nqfa_size
+#define        fa_nqblocksize          fa_un.fa_nqnfs.nqfa_blocksize
+#define        fa_nqrdev               fa_un.fa_nqnfs.nqfa_rdev
+#define        fa_nqbytes              fa_un.fa_nqnfs.nqfa_bytes
+#define        fa_nqfsid               fa_un.fa_nqnfs.nqfa_fsid
+#define        fa_nqfileid             fa_un.fa_nqnfs.nqfa_fileid
+#define        fa_nqatime              fa_un.fa_nqnfs.nqfa_atime
+#define        fa_nqmtime              fa_un.fa_nqnfs.nqfa_mtime
+#define        fa_nqctime              fa_un.fa_nqnfs.nqfa_ctime
+#define        fa_nqflags              fa_un.fa_nqnfs.nqfa_flags
+#define        fa_nqgen                fa_un.fa_nqnfs.nqfa_gen
+#define        fa_nqfilerev            fa_un.fa_nqnfs.nqfa_filerev
+
+struct nfsv2_sattr {
+       u_int32_t sa_mode;
+       u_int32_t sa_uid;
+       u_int32_t sa_gid;
+       union {
+               struct {
+                       u_int32_t nfssa_size;
+                       struct nfsv2_time nfssa_atime;
+                       struct nfsv2_time nfssa_mtime;
+               } sa_nfsv2;
+               struct {
+                       struct {
+                               u_int32_t nqsa_qsize[2];
+                       } nqsa_size;
+                       struct nqnfs_time nqsa_atime;
+                       struct nqnfs_time nqsa_mtime;
+                       u_int32_t nqsa_flags;
+                       u_int32_t nqsa_rdev;
+               } sa_nqnfs;
+       } sa_un;
+};
+
+/* and some ugly defines for accessing the unions */
+#define        sa_nfssize              sa_un.sa_nfsv2.nfssa_size
+#define        sa_nfsatime             sa_un.sa_nfsv2.nfssa_atime
+#define        sa_nfsmtime             sa_un.sa_nfsv2.nfssa_mtime
+#define        sa_nqsize               sa_un.sa_nqnfs.nqsa_size
+#define        sa_nqatime              sa_un.sa_nqnfs.nqsa_atime
+#define        sa_nqmtime              sa_un.sa_nqnfs.nqsa_mtime
+#define        sa_nqflags              sa_un.sa_nqnfs.nqsa_flags
+#define        sa_nqrdev               sa_un.sa_nqnfs.nqsa_rdev
+
+struct nfsv2_statfs {
+       u_int32_t sf_tsize;
+       u_int32_t sf_bsize;
+       u_int32_t sf_blocks;
+       u_int32_t sf_bfree;
+       u_int32_t sf_bavail;
+       u_int32_t sf_files;     /* Nqnfs only */
+       u_int32_t sf_ffree;     /* ditto      */
+};
diff --git a/tcpdump.tproj/ntp.h b/tcpdump.tproj/ntp.h
new file mode 100644 (file)
index 0000000..dd69af9
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/ntp.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ */
+
+/*
+ * Based on ntp.h from the U of MD implementation
+ *     This file is based on Version 2 of the NTP spec (RFC1119).
+ */
+
+/*
+ *  Definitions for the masses
+ */
+#define        JAN_1970        2208988800      /* 1970 - 1900 in seconds */
+
+/*
+ * Structure definitions for NTP fixed point values
+ *
+ *    0                          1                   2                   3
+ *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                        Integer Part                          |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                        Fraction Part                         |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *    0                          1                   2                   3
+ *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |           Integer Part       |     Fraction Part             |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+struct l_fixedpt {
+       u_int32_t int_part;
+       u_int32_t fraction;
+};
+
+struct s_fixedpt {
+       u_short int_part;
+       u_short fraction;
+};
+
+/*  =================  Table 3.3. Packet Variables   ================= */
+/*
+ *    0                          1                   2                   3
+ *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |LI | VN  | Mode|   Stratum    |      Poll     |   Precision   |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                    Synchronizing Distance                    |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                   Synchronizing Dispersion                   |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                 Reference Clock Identifier                   |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                                                              |
+ *   |                Reference Timestamp (64 bits)                 |
+ *   |                                                              |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                                                              |
+ *   |                Originate Timestamp (64 bits)                 |
+ *   |                                                              |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                                                              |
+ *   |                 Receive Timestamp (64 bits)                  |
+ *   |                                                              |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                                                              |
+ *   |                 Transmit Timestamp (64 bits)                 |
+ *   |                                                              |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+struct ntpdata {
+       u_char status;          /* status of local clock and leap info */
+       u_char stratum;         /* Stratum level */
+       u_char ppoll;           /* poll value */
+       int precision:8;
+       struct s_fixedpt distance;
+       struct s_fixedpt dispersion;
+       u_int32_t refid;
+       struct l_fixedpt reftime;
+       struct l_fixedpt org;
+       struct l_fixedpt rec;
+       struct l_fixedpt xmt;
+};
+/*
+ *     Leap Second Codes (high order two bits)
+ */
+#define        NO_WARNING      0x00    /* no warning */
+#define        PLUS_SEC        0x40    /* add a second (61 seconds) */
+#define        MINUS_SEC       0x80    /* minus a second (59 seconds) */
+#define        ALARM           0xc0    /* alarm condition (clock unsynchronized) */
+
+/*
+ *     Clock Status Bits that Encode Version
+ */
+#define        NTPVERSION_1    0x08
+#define        VERSIONMASK     0x38
+#define LEAPMASK       0xc0
+#define        MODEMASK        0x07
+
+/*
+ *     Code values
+ */
+#define        MODE_UNSPEC     0       /* unspecified */
+#define        MODE_SYM_ACT    1       /* symmetric active */
+#define        MODE_SYM_PAS    2       /* symmetric passive */
+#define        MODE_CLIENT     3       /* client */
+#define        MODE_SERVER     4       /* server */
+#define        MODE_BROADCAST  5       /* broadcast */
+#define        MODE_RES1       6       /* reserved */
+#define        MODE_RES2       7       /* reserved */
+
+/*
+ *     Stratum Definitions
+ */
+#define        UNSPECIFIED     0
+#define        PRIM_REF        1       /* radio clock */
+#define        INFO_QUERY      62      /* **** THIS implementation dependent **** */
+#define        INFO_REPLY      63      /* **** THIS implementation dependent **** */
diff --git a/tcpdump.tproj/os-solaris2.h b/tcpdump.tproj/os-solaris2.h
new file mode 100644 (file)
index 0000000..440d65c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/os-solaris2.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)
+ */
+
+/* Prototypes missing in SunOS 5 */
+int    daemon(int, int);
+int    dn_expand(u_char *, u_char *, u_char *, u_char *, int);
+int    dn_skipname(u_char *, u_char *);
+int    flock(int, int);
+int    getdtablesize(void);
+int    gethostname(char *, int);
+int    getpagesize(void);
+char   *getusershell(void);
+char   *getwd(char *);
+int    iruserok(u_int, int, char *, char *);
+#ifdef __STDC__
+struct utmp;
+void   login(struct utmp *);
+#endif
+int    logout(const char *);
+int    res_query(char *, int, int, u_char *, int);
+int    setenv(const char *, const char *, int);
+#if defined(_STDIO_H) && defined(HAVE_SETLINEBUF)
+int    setlinebuf(FILE *);
+#endif
+int    sigblock(int);
+int    sigsetmask(int);
+char    *strerror(int);
+int    snprintf(char *, size_t, const char *, ...);
+int    strcasecmp(const char *, const char *);
+void   unsetenv(const char *);
+#ifdef __STDC__
+struct timeval;
+#endif
+int    utimes(const char *, struct timeval *);
diff --git a/tcpdump.tproj/os-sunos4.h b/tcpdump.tproj/os-sunos4.h
new file mode 100644 (file)
index 0000000..01389d1
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1990, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/os-sunos4.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)
+ */
+
+/* Prototypes missing in SunOS 4 */
+#ifdef FILE
+int    _filbuf(FILE *);
+int    _flsbuf(u_char, FILE *);
+int    fclose(FILE *);
+int    fflush(FILE *);
+int    fgetc(FILE *);
+int    fprintf(FILE *, const char *, ...);
+int    fputc(int, FILE *);
+int    fputs(const char *, FILE *);
+u_int  fread(void *, u_int, u_int, FILE *);
+int    fseek(FILE *, long, int);
+u_int  fwrite(const void *, u_int, u_int, FILE *);
+int    pclose(FILE *);
+void   rewind(FILE *);
+void   setbuf(FILE *, char *);
+int    setlinebuf(FILE *);
+int    ungetc(int, FILE *);
+int    vfprintf(FILE *, const char *, ...);
+int    vprintf(const char *, ...);
+#endif
+
+#if __GNUC__ <= 1
+int    read(int, char *, u_int);
+int    write(int, char *, u_int);
+#endif
+
+long   a64l(const char *);
+#ifdef __STDC__
+struct sockaddr;
+#endif
+int    accept(int, struct sockaddr *, int *);
+int    bind(int, struct sockaddr *, int);
+int    bcmp(const void *, const void *, u_int);
+void   bcopy(const void *, void *, u_int);
+void   bzero(void *, int);
+int    chroot(const char *);
+int    close(int);
+void   closelog(void);
+int    connect(int, struct sockaddr *, int);
+char   *crypt(const char *, const char *);
+int    daemon(int, int);
+int    fchmod(int, int);
+int    fchown(int, int, int);
+void   endgrent(void);
+void   endpwent(void);
+void   endservent(void);
+#ifdef __STDC__
+struct ether_addr;
+#endif
+struct ether_addr *ether_aton(const char *);
+int    flock(int, int);
+#ifdef __STDC__
+struct stat;
+#endif
+int    fstat(int, struct stat *);
+#ifdef __STDC__
+struct statfs;
+#endif
+int    fstatfs(int, struct statfs *);
+int    fsync(int);
+#ifdef __STDC__
+struct timeb;
+#endif
+int    ftime(struct timeb *);
+int    ftruncate(int, off_t);
+int    getdtablesize(void);
+long   gethostid(void);
+int    gethostname(char *, int);
+int    getopt(int, char * const *, const char *);
+int    getpagesize(void);
+char   *getpass(char *);
+int    getpeername(int, struct sockaddr *, int *);
+int    getpriority(int, int);
+#ifdef __STDC__
+struct rlimit;
+#endif
+int    getrlimit(int, struct rlimit *);
+int    getsockname(int, struct sockaddr *, int *);
+int    getsockopt(int, int, int, char *, int *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int    gettimeofday(struct timeval *, struct timezone *);
+char   *getusershell(void);
+char   *getwd(char *);
+int    initgroups(const char *, int);
+int    ioctl(int, int, caddr_t);
+int    iruserok(u_long, int, char *, char *);
+int    isatty(int);
+int    killpg(int, int);
+int    listen(int, int);
+#ifdef __STDC__
+struct utmp;
+#endif
+void   login(struct utmp *);
+int    logout(const char *);
+off_t  lseek(int, off_t, int);
+int    lstat(const char *, struct stat *);
+int    mkstemp(char *);
+char   *mktemp(char *);
+int    munmap(caddr_t, int);
+void   openlog(const char *, int, int);
+void   perror(const char *);
+int    printf(const char *, ...);
+int    puts(const char *);
+long   random(void);
+int    readlink(const char *, char *, int);
+#ifdef __STDC__
+struct iovec;
+#endif
+int    readv(int, struct iovec *, int);
+int    recv(int, char *, u_int, int);
+int    recvfrom(int, char *, u_int, int, struct sockaddr *, int *);
+int    rename(const char *, const char *);
+int    rcmd(char **, u_short, char *, char *, char *, int *);
+int    rresvport(int *);
+int    send(int, char *, u_int, int);
+int    sendto(int, char *, u_int, int, struct sockaddr *, int);
+int    setenv(const char *, const char *, int);
+int    seteuid(int);
+int    setpriority(int, int, int);
+int    select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+int    setpgrp(int, int);
+void   setpwent(void);
+int    setrlimit(int, struct rlimit *);
+void   setservent(int);
+int    setsockopt(int, int, int, char *, int);
+int    shutdown(int, int);
+int    sigblock(int);
+void   (*signal (int, void (*) (int))) (int);
+int    sigpause(int);
+int    sigsetmask(int);
+#ifdef __STDC__
+struct sigvec;
+#endif
+int    sigvec(int, struct sigvec *, struct sigvec*);
+int    snprintf(char *, size_t, const char *, ...);
+int    socket(int, int, int);
+int    socketpair(int, int, int, int *);
+int    symlink(const char *, const char *);
+void   srandom(int);
+int    sscanf(char *, const char *, ...);
+int    stat(const char *, struct stat *);
+int    statfs(char *, struct statfs *);
+char   *strerror(int);
+int    strcasecmp(const char *, const char *);
+#ifdef __STDC__
+struct tm;
+#endif
+int    strftime(char *, int, char *, struct tm *);
+int    strncasecmp(const char *, const char *, int);
+long   strtol(const char *, char **, int);
+void   sync(void);
+void   syslog(int, const char *, ...);
+int    system(const char *);
+long   tell(int);
+time_t time(time_t *);
+char   *timezone(int, int);
+int    tolower(int);
+int    toupper(int);
+int    truncate(char *, off_t);
+void   unsetenv(const char *);
+int    vfork(void);
+int    vsprintf(char *, const char *, ...);
+int    writev(int, struct iovec *, int);
+#ifdef __STDC__
+struct rusage;
+#endif
+int    utimes(const char *, struct timeval *);
+#if __GNUC__ <= 1
+int    wait(int *);
+pid_t  wait3(int *, int, struct rusage *);
+#endif
+
+/* Ugly signal hacking */
+#ifdef SIG_ERR
+#undef SIG_ERR
+#define SIG_ERR                (void (*)(int))-1
+#undef SIG_DFL
+#define SIG_DFL                (void (*)(int))0
+#undef SIG_IGN
+#define SIG_IGN                (void (*)(int))1
+
+#ifdef KERNEL
+#undef SIG_CATCH
+#define SIG_CATCH      (void (*)(int))2
+#endif
+#undef SIG_HOLD
+#define SIG_HOLD       (void (*)(int))3
+#endif
diff --git a/tcpdump.tproj/os-ultrix4.h b/tcpdump.tproj/os-ultrix4.h
new file mode 100644 (file)
index 0000000..623d80a
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/os-ultrix4.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)
+ */
+
+/* Prototypes missing in Ultrix 4 */
+int    bcmp(const char *, const char *, u_int);
+void   bcopy(const void *, void *, u_int);
+void   bzero(void *, u_int);
+void   endservent(void);
+int    getopt(int, char * const *, const char *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int    gettimeofday(struct timeval *, struct timezone *);
+int    ioctl(int, int, caddr_t);
+int    pfopen(char *, int);
+int    setlinebuf(FILE *);
+int    socket(int, int, int);
+int    strcasecmp(const char *, const char *);
diff --git a/tcpdump.tproj/ospf.h b/tcpdump.tproj/ospf.h
new file mode 100644 (file)
index 0000000..9be2236
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
+ */
+#define        OSPF_TYPE_UMD   0       /* UMd's special monitoring packets */
+#define        OSPF_TYPE_HELLO 1       /* Hello */
+#define        OSPF_TYPE_DB    2       /* Database Description */
+#define        OSPF_TYPE_LSR   3       /* Link State Request */
+#define        OSPF_TYPE_LSU   4       /* Link State Update */
+#define        OSPF_TYPE_LSA   5       /* Link State Ack */
+#define        OSPF_TYPE_MAX   6
+
+/* Options *_options   */
+#define OSPF_OPTION_T  0x01    /* T bit: TOS support   */
+#define OSPF_OPTION_E  0x02    /* E bit: External routes advertised    */
+#define        OSPF_OPTION_MC  0x04    /* MC bit: Multicast capable */
+
+/* ospf_authtype       */
+#define        OSPF_AUTH_NONE          0       /* No auth-data */
+#define        OSPF_AUTH_SIMPLE        1       /* Simple password */
+
+/* db_flags    */
+#define        OSPF_DB_INIT            0x04        /*  */
+#define        OSPF_DB_MORE            0x02
+#define        OSPF_DB_MASTER          0x01
+
+/* ls_type     */
+#define        LS_TYPE_ROUTER          1   /* router link */
+#define        LS_TYPE_NETWORK         2   /* network link */
+#define        LS_TYPE_SUM_IP          3   /* summary link */
+#define        LS_TYPE_SUM_ABR         4   /* summary area link */
+#define        LS_TYPE_ASE             5   /* ASE  */
+#define        LS_TYPE_GROUP           6   /* Group membership (multicast */
+                                   /* extensions 23 July 1991) */
+#define        LS_TYPE_MAX             7
+
+/*************************************************
+ *
+ * is the above a bug in the documentation?
+ *
+ *************************************************/
+
+
+/* rla_link.link_type  */
+#define        RLA_TYPE_ROUTER         1   /* point-to-point to another router */
+#define        RLA_TYPE_TRANSIT        2   /* connection to transit network    */
+#define        RLA_TYPE_STUB           3   /* connection to stub network       */
+#define RLA_TYPE_VIRTUAL       4   /* virtual link                     */
+
+/* rla_flags   */
+#define        RLA_FLAG_B      0x01
+#define        RLA_FLAG_E      0x02
+#define        RLA_FLAG_W1     0x04
+#define        RLA_FLAG_W2     0x08
+
+/* sla_tosmetric breakdown     */
+#define        SLA_MASK_TOS            0x7f000000
+#define        SLA_MASK_METRIC         0x00ffffff
+#define SLA_SHIFT_TOS          24
+
+/* asla_tosmetric breakdown    */
+#define        ASLA_FLAG_EXTERNAL      0x80000000
+#define        ASLA_MASK_TOS           0x7f000000
+#define        ASLA_SHIFT_TOS          24
+#define        ASLA_MASK_METRIC        0x00ffffff
+
+/* multicast vertex type */
+#define        MCLA_VERTEX_ROUTER      1
+#define        MCLA_VERTEX_NETWORK     2
+
+/* link state advertisement header */
+struct lsa_hdr {
+    u_short ls_age;
+    u_char ls_options;
+    u_char ls_type;
+    struct in_addr ls_stateid;
+    struct in_addr ls_router;
+    u_int32_t ls_seq;
+    u_short ls_chksum;
+    u_short ls_length;
+} ;
+
+/* link state advertisement */
+struct lsa {
+    struct lsa_hdr ls_hdr;
+
+    /* Link state types */
+    union {
+       /* Router links advertisements */
+       struct {
+           u_char rla_flags;
+           u_char rla_zero[1];
+           u_short rla_count;
+           struct rlalink {
+               struct in_addr link_id;
+               struct in_addr link_data;
+               u_char link_type;
+               u_char link_toscount;
+               u_short link_tos0metric;
+           } rla_link[1];              /* may repeat   */
+       } un_rla;
+
+       /* Network links advertisements */
+       struct {
+           struct in_addr nla_mask;
+           struct in_addr nla_router[1];       /* may repeat   */
+       } un_nla;
+
+       /* Summary links advertisements */
+       struct {
+           struct in_addr sla_mask;
+           u_int32_t sla_tosmetric[1]; /* may repeat   */
+       } un_sla;
+
+       /* AS external links advertisements */
+       struct {
+           struct in_addr asla_mask;
+           struct aslametric {
+               u_int32_t asla_tosmetric;
+               struct in_addr asla_forward;
+               struct in_addr asla_tag;
+           } asla_metric[1];           /* may repeat   */
+       } un_asla;
+
+       /* Multicast group membership */
+       struct mcla {
+           u_int32_t mcla_vtype;
+           struct in_addr mcla_vid;
+       } un_mcla[1];
+    } lsa_un;
+} ;
+
+
+/*
+ * TOS metric struct (will be 0 or more in router links update)
+ */
+struct tos_metric {
+    u_char tos_type;
+    u_char tos_zero;
+    u_short tos_metric;
+} ;
+
+#define        OSPF_AUTH_SIZE  8
+
+/*
+ * the main header
+ */
+struct ospfhdr {
+    u_char ospf_version;
+    u_char ospf_type;
+    u_short ospf_len;
+    struct in_addr ospf_routerid;
+    struct in_addr ospf_areaid;
+    u_short ospf_chksum;
+    u_short ospf_authtype;
+    u_char ospf_authdata[OSPF_AUTH_SIZE];
+    union {
+
+       /* Hello packet */
+       struct {
+           struct in_addr hello_mask;
+           u_short hello_helloint;
+           u_char hello_options;
+           u_char hello_priority;
+           u_int32_t hello_deadint;
+           struct in_addr hello_dr;
+           struct in_addr hello_bdr;
+           struct in_addr hello_neighbor[1]; /* may repeat     */
+       } un_hello;
+
+       /* Database Description packet */
+       struct {
+           u_char db_zero[2];
+           u_char db_options;
+           u_char db_flags;
+           u_int32_t db_seq;
+           struct lsa_hdr db_lshdr[1]; /* may repeat   */
+       } un_db;
+
+       /* Link State Request */
+       struct lsr {
+           u_int32_t ls_type;
+           struct in_addr ls_stateid;
+           struct in_addr ls_router;
+       } un_lsr[1];            /* may repeat   */
+
+       /* Link State Update */
+       struct {
+           u_int32_t lsu_count;
+           struct lsa lsu_lsa[1]; /* may repeat        */
+       } un_lsu;
+
+       /* Link State Acknowledgement */
+       struct {
+           struct lsa_hdr lsa_lshdr[1]; /* may repeat  */
+       } un_lsa ;
+    } ospf_un ;
+} ;
+
+#define        ospf_hello      ospf_un.un_hello
+#define        ospf_db         ospf_un.un_db
+#define        ospf_lsr        ospf_un.un_lsr
+#define        ospf_lsu        ospf_un.un_lsu
+#define        ospf_lsa        ospf_un.un_lsa
+
diff --git a/tcpdump.tproj/parsenfsfh.c b/tcpdump.tproj/parsenfsfh.c
new file mode 100644 (file)
index 0000000..bdfdf43
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * parsenfsfh.c - portable parser for NFS file handles
+ *                     uses all sorts of heuristics
+ *
+ * Jeffrey C. Mogul
+ * Digital Equipment Corporation
+ * Western Research Laboratory
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/parsenfsfh.c,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "nfsfh.h"
+
+/*
+ * This routine attempts to parse a file handle (in network byte order),
+ * using heuristics to guess what kind of format it is in.  See the
+ * file "fhandle_layouts" for a detailed description of the various
+ * patterns we know about.
+ *
+ * The file handle is parsed into our internal representation of a
+ * file-system id, and an internal representation of an inode-number.
+ */
+
+#define        FHT_UNKNOWN     0
+#define        FHT_AUSPEX      1
+#define        FHT_DECOSF      2
+#define        FHT_IRIX4       3
+#define        FHT_IRIX5       4
+#define        FHT_SUNOS3      5
+#define        FHT_SUNOS4      6
+#define        FHT_ULTRIX      7
+#define        FHT_VMSUCX      8
+#define        FHT_SUNOS5      9
+#define        FHT_AIX32       10
+#define        FHT_HPUX9       11
+
+#ifdef ultrix
+/* Nasty hack to keep the Ultrix C compiler from emitting bogus warnings */
+#define        XFF(x)  ((u_int32_t)(x))
+#else
+#define        XFF(x)  (x)
+#endif
+
+#define        make_uint32(msb,b,c,lsb)\
+       (XFF(lsb) + (XFF(c)<<8) + (XFF(b)<<16) + (XFF(msb)<<24))
+
+#define        make_uint24(msb,b, lsb)\
+       (XFF(lsb) + (XFF(b)<<8) + (XFF(msb)<<16))
+
+#define        make_uint16(msb,lsb)\
+       (XFF(lsb) + (XFF(msb)<<8))
+
+#ifdef __alpha
+       /* or other 64-bit systems */
+#define        make_uint48(msb,b,c,d,e,lsb)\
+       ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24) + ((b)<<32) + ((msb)<<40))
+#else
+       /* on 32-bit systems ignore high-order bits */
+#define        make_uint48(msb,b,c,d,e,lsb)\
+       ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24))
+#endif
+
+static int is_UCX(unsigned char *);
+
+void
+Parse_fh(fh, fsidp, inop, osnamep, fsnamep, ourself)
+register caddr_t *fh;
+my_fsid *fsidp;
+ino_t *inop;
+char **osnamep;                /* if non-NULL, return OS name here */
+char **fsnamep;                /* if non-NULL, return server fs name here (for VMS) */
+int ourself;           /* true if file handle was generated on this host */
+{
+       register unsigned char *fhp = (unsigned char *)fh;
+       u_int32_t temp;
+       int fhtype = FHT_UNKNOWN;
+
+       if (ourself) {
+           /* File handle generated on this host, no need for guessing */
+#if    defined(IRIX40)
+           fhtype = FHT_IRIX4;
+#endif
+#if    defined(IRIX50)
+           fhtype = FHT_IRIX5;
+#endif
+#if    defined(IRIX51)
+           fhtype = FHT_IRIX5;
+#endif
+#if    defined(SUNOS4)
+           fhtype = FHT_SUNOS4;
+#endif
+#if    defined(SUNOS5)
+           fhtype = FHT_SUNOS5;
+#endif
+#if    defined(ultrix)
+           fhtype = FHT_ULTRIX;
+#endif
+#if    defined(__osf__)
+           fhtype = FHT_DECOSF;
+#endif
+       }
+       /*
+        * This is basically a big decision tree
+        */
+       else if ((fhp[0] == 0) && (fhp[1] == 0)) {
+           /* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */
+           /* probably rules out HP-UX, AIX unless they allow major=0 */
+           if ((fhp[2] == 0) && (fhp[3] == 0)) {
+               /* bytes[2,3] == (0,0); must be Auspex */
+               /* XXX or could be Ultrix+MASSBUS "hp" disk? */
+               fhtype = FHT_AUSPEX;
+           }
+           else {
+               /*
+                * bytes[2,3] != (0,0); rules out Auspex, could be
+                * DECOSF, SUNOS4, or IRIX4
+                */
+               if ((fhp[4] != 0) && (fhp[5] == 0) &&
+                       (fhp[8] == 12) && (fhp[9] == 0)) {
+                   /* seems to be DECOSF, with minor == 0 */
+                   fhtype = FHT_DECOSF;
+               }
+               else {
+                   /* could be SUNOS4 or IRIX4 */
+                   /* XXX the test of fhp[5] == 8 could be wrong */
+                   if ((fhp[4] == 0) && (fhp[5] == 8) && (fhp[6] == 0) &&
+                       (fhp[7] == 0)) {
+                       /* looks like a length, not a file system typecode */
+                       fhtype = FHT_IRIX4;
+                   }
+                   else {
+                       /* by elimination */
+                       fhtype = FHT_SUNOS4;
+                   }
+               }
+           }
+       }
+       else {
+           /*
+            * bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4
+            * could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5
+            * could be AIX, HP-UX
+            */
+           if ((fhp[2] == 0) && (fhp[3] == 0)) {
+               /*
+                * bytes[2,3] == (0,0); rules out OSF, probably not UCX
+                * (unless the exported device name is just one letter!),
+                * could be Ultrix, IRIX5, AIX, or SUNOS5
+                * might be HP-UX (depends on their values for minor devs)
+                */
+               /*XXX we probably only need to test of these two bytes */
+               if ((fhp[21] == 0) && (fhp[23] == 0)) {
+                   fhtype = FHT_ULTRIX;
+               }
+               else {
+                   /* Could be SUNOS5/IRIX5, maybe AIX */
+                   /* XXX no obvious difference between SUNOS5 and IRIX5 */
+                   if (fhp[9] == 10)
+                       fhtype = FHT_SUNOS5;
+                   /* XXX what about AIX? */
+               }
+           }
+           else {
+               /*
+                * bytes[2,3] != (0,0); rules out Ultrix, could be
+                * DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX
+                */
+               if ((fhp[8] == 12) && (fhp[9] == 0)) {
+                   fhtype = FHT_DECOSF;
+               }
+               else if ((fhp[8] == 0) && (fhp[9] == 10)) {
+                   /* could be SUNOS5/IRIX5, AIX, HP-UX */
+                   if ((fhp[7] == 0) && (fhp[6] == 0) &&
+                       (fhp[5] == 0) && (fhp[4] == 0)) {
+                       /* XXX is this always true of HP-UX? */
+                       fhtype = FHT_HPUX9;
+                   }
+                   else if (fhp[7] == 2) {
+                       /* This would be MNT_NFS on AIX, which is impossible */
+                       fhtype = FHT_SUNOS5;    /* or maybe IRIX5 */
+                   }
+                   else {
+                       /*
+                        * XXX Could be SUNOS5/IRIX5 or AIX.  I don't
+                        * XXX see any way to disambiguate these, so
+                        * XXX I'm going with the more likely guess.
+                        * XXX Sorry, Big Blue.
+                        */
+                       fhtype = FHT_SUNOS5;    /* or maybe IRIX5 */
+                   }
+               }
+               else {
+                   if (is_UCX(fhp)) {
+                       fhtype = FHT_VMSUCX;
+                   }
+                   else {
+                       fhtype = FHT_UNKNOWN;
+                   }
+               }
+           }
+       }
+
+       /* XXX still needs to handle SUNOS3 */
+
+       switch (fhtype) {
+       case FHT_AUSPEX:
+           fsidp->Fsid_dev.Minor = fhp[7];
+           fsidp->Fsid_dev.Major = fhp[6];
+           fsidp->fsid_code = 0;
+
+           temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
+           *inop = temp;
+
+           if (osnamep)
+               *osnamep = "Auspex";
+           break;
+
+       case FHT_DECOSF:
+           fsidp->fsid_code = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]);
+                       /* XXX could ignore 3 high-order bytes */
+
+           temp = make_uint32(fhp[3], fhp[2], fhp[1], fhp[0]);
+           fsidp->Fsid_dev.Minor = temp & 0xFFFFF;
+           fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF;
+
+           temp = make_uint32(fhp[15], fhp[14], fhp[13], fhp[12]);
+           *inop = temp;
+           if (osnamep)
+               *osnamep = "OSF";
+           break;
+
+       case FHT_IRIX4:
+           fsidp->Fsid_dev.Minor = fhp[3];
+           fsidp->Fsid_dev.Major = fhp[2];
+           fsidp->fsid_code = 0;
+
+           temp = make_uint32(fhp[8], fhp[9], fhp[10], fhp[11]);
+           *inop = temp;
+
+           if (osnamep)
+               *osnamep = "IRIX4";
+           break;
+
+       case FHT_IRIX5:
+           fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]);
+           fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]);
+           fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
+
+           temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
+           *inop = temp;
+
+           if (osnamep)
+               *osnamep = "IRIX5";
+           break;
+
+       case FHT_SUNOS3:
+           if (osnamep)
+               *osnamep = "SUNOS3";
+           break;
+
+       case FHT_SUNOS4:
+           fsidp->Fsid_dev.Minor = fhp[3];
+           fsidp->Fsid_dev.Major = fhp[2];
+           fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
+
+           temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
+           *inop = temp;
+
+           if (osnamep)
+               *osnamep = "SUNOS4";
+           break;
+
+       case FHT_SUNOS5:
+           temp = make_uint16(fhp[0], fhp[1]);
+           fsidp->Fsid_dev.Major = (temp>>2) &  0x3FFF;
+           temp = make_uint24(fhp[1], fhp[2], fhp[3]);
+           fsidp->Fsid_dev.Minor = temp & 0x3FFFF;
+           fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
+
+           temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
+           *inop = temp;
+
+           if (osnamep)
+               *osnamep = "SUNOS5";
+           break;
+
+       case FHT_ULTRIX:
+           fsidp->fsid_code = 0;
+           fsidp->Fsid_dev.Minor = fhp[0];
+           fsidp->Fsid_dev.Major = fhp[1];
+
+           temp = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]);
+           *inop = temp;
+           if (osnamep)
+               *osnamep = "Ultrix";
+           break;
+
+       case FHT_VMSUCX:
+           /* No numeric file system ID, so hash on the device-name */
+           if (sizeof(*fsidp) >= 14) {
+               if (sizeof(*fsidp) > 14)
+                   memset((char *)fsidp, 0, sizeof(*fsidp));
+               memcpy((char *)fsidp, fh, 14);  /* just use the whole thing */
+           }
+           else {
+               u_int32_t tempa[4];     /* at least 16 bytes, maybe more */
+
+               memset((char *)tempa, 0, sizeof(tempa));
+               memcpy((char *)tempa, fh, 14);  /* ensure alignment */
+               fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1);
+               fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1);
+               fsidp->fsid_code = 0;
+           }
+
+           /* VMS file ID is: (RVN, FidHi, FidLo) */
+           *inop = make_uint32(fhp[26], fhp[27], fhp[23], fhp[22]);
+
+           /* Caller must save (and null-terminate?) this value */
+           if (fsnamep)
+               *fsnamep = (char *)&(fhp[1]);
+
+           if (osnamep)
+               *osnamep = "VMS";
+           break;
+
+       case FHT_AIX32:
+           fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]);
+           fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]);
+           fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
+
+           temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
+           *inop = temp;
+
+           if (osnamep)
+               *osnamep = "AIX32";
+           break;
+
+       case FHT_HPUX9:
+           fsidp->Fsid_dev.Major = fhp[0];
+           temp = make_uint24(fhp[1], fhp[2], fhp[3]);
+           fsidp->Fsid_dev.Minor = temp;
+           fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
+
+           temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
+           *inop = temp;
+
+           if (osnamep)
+               *osnamep = "HPUX9";
+           break;
+
+       case FHT_UNKNOWN:
+#ifdef DEBUG
+           {
+               /* XXX debugging */
+               int i;
+               for (i = 0; i < 32; i++)
+                       (void)fprintf(stderr, "%x.", fhp[i]);
+               (void)fprintf(stderr, "\n");
+           }
+#endif
+           /* XXX for now, give "bogus" values to aid debugging */
+           fsidp->fsid_code = 0;
+           fsidp->Fsid_dev.Minor = 257;
+           fsidp->Fsid_dev.Major = 257;
+           *inop = 1;
+
+           /* display will show this string instead of (257,257) */
+           if (fsnamep)
+               *fsnamep = "Unknown";
+
+           if (osnamep)
+               *osnamep = "Unknown";
+           break;
+
+       }
+}
+
+/*
+ * Is this a VMS UCX file handle?
+ *     Check for:
+ *     (1) leading code byte   [XXX not yet]
+ *     (2) followed by string of printing chars & spaces
+ *     (3) followed by string of nulls
+ */
+static int
+is_UCX(fhp)
+unsigned char *fhp;
+{
+       register int i;
+       int seen_null = 0;
+
+       for (i = 1; i < 14; i++) {
+           if (isprint(fhp[i])) {
+               if (seen_null)
+                  return(0);
+               else
+                  continue;
+           }
+           else if (fhp[i] == 0) {
+               seen_null = 1;
+               continue;
+           }
+           else
+               return(0);
+       }
+
+       return(1);
+}
diff --git a/tcpdump.tproj/print-arp.c b/tcpdump.tproj/print-arp.c
new file mode 100644 (file)
index 0000000..0fe851b
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-arp.c,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ethertype.h"
+#include "extract.h"                   /* must come after interface.h */
+
+/* Compatibility */
+#ifndef REVARP_REQUEST
+#define REVARP_REQUEST         3
+#endif
+#ifndef REVARP_REPLY
+#define REVARP_REPLY           4
+#endif
+
+static u_char ezero[6];
+
+void
+arp_print(register const u_char *bp, u_int length, u_int caplen)
+{
+       register const struct ether_arp *ap;
+       register const struct ether_header *eh;
+       register u_short pro, hrd, op;
+
+       ap = (struct ether_arp *)bp;
+       if ((u_char *)(ap + 1) > snapend) {
+               printf("[|arp]");
+               return;
+       }
+       if (length < sizeof(struct ether_arp)) {
+               (void)printf("truncated-arp");
+               default_print((u_char *)ap, length);
+               return;
+       }
+
+       pro = EXTRACT_16BITS(&ap->arp_pro);
+       hrd = EXTRACT_16BITS(&ap->arp_hrd);
+       op = EXTRACT_16BITS(&ap->arp_op);
+
+       if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
+           || ap->arp_hln != sizeof(SHA(ap))
+           || ap->arp_pln != sizeof(SPA(ap))) {
+               (void)printf("arp-#%d for proto #%d (%d) hardware #%d (%d)",
+                               op, pro, ap->arp_pln,
+                               hrd, ap->arp_hln);
+               return;
+       }
+       if (pro == ETHERTYPE_TRAIL)
+               (void)printf("trailer-");
+       eh = (struct ether_header *)packetp;
+       switch (op) {
+
+       case ARPOP_REQUEST:
+               (void)printf("arp who-has %s", ipaddr_string(TPA(ap)));
+               if (memcmp((char *)ezero, (char *)THA(ap), 6) != 0)
+                       (void)printf(" (%s)", etheraddr_string(THA(ap)));
+               (void)printf(" tell %s", ipaddr_string(SPA(ap)));
+               if (memcmp((char *)ESRC(eh), (char *)SHA(ap), 6) != 0)
+                       (void)printf(" (%s)", etheraddr_string(SHA(ap)));
+               break;
+
+       case ARPOP_REPLY:
+               (void)printf("arp reply %s", ipaddr_string(SPA(ap)));
+               if (memcmp((char *)ESRC(eh), (char *)SHA(ap), 6) != 0)
+                       (void)printf(" (%s)", etheraddr_string(SHA(ap)));
+               (void)printf(" is-at %s", etheraddr_string(SHA(ap)));
+               if (memcmp((char *)EDST(eh), (char *)THA(ap), 6) != 0)
+                       (void)printf(" (%s)", etheraddr_string(THA(ap)));
+               break;
+
+       case REVARP_REQUEST:
+               (void)printf("rarp who-is %s tell %s",
+                       etheraddr_string(THA(ap)),
+                       etheraddr_string(SHA(ap)));
+               break;
+
+       case REVARP_REPLY:
+               (void)printf("rarp reply %s at %s",
+                       etheraddr_string(THA(ap)),
+                       ipaddr_string(TPA(ap)));
+               break;
+
+       default:
+               (void)printf("arp-#%d", op);
+               default_print((u_char *)ap, caplen);
+               return;
+       }
+       if (hrd != ARPHRD_ETHER)
+               printf(" hardware #%d", hrd);
+}
diff --git a/tcpdump.tproj/print-atalk.c b/tcpdump.tproj/print-atalk.c
new file mode 100644 (file)
index 0000000..f939466
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print AppleTalk packets.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-atalk.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ethertype.h"
+#include "extract.h"                   /* must come after interface.h */
+#include "appletalk.h"
+
+static struct tok type2str[] = {
+       { ddpRTMP,              "rtmp" },
+       { ddpRTMPrequest,       "rtmpReq" },
+       { ddpECHO,              "echo" },
+       { ddpIP,                "IP" },
+       { ddpARP,               "ARP" },
+       { ddpKLAP,              "KLAP" },
+       { 0,                    NULL }
+};
+
+struct aarp {
+       u_short htype, ptype;
+       u_char  halen, palen;
+       u_short op;
+       u_char  hsaddr[6];
+       u_char  psaddr[4];
+       u_char  hdaddr[6];
+       u_char  pdaddr[4];
+};
+
+static char tstr[] = "[|atalk]";
+
+static void atp_print(const struct atATP *, u_int);
+static void atp_bitmap_print(u_char);
+static void nbp_print(const struct atNBP *, u_int, u_short, u_char, u_char);
+static const char *print_cstring(const char *, const u_char *);
+static const struct atNBPtuple *nbp_tuple_print(const struct atNBPtuple *,
+                                               const u_char *,
+                                               u_short, u_char, u_char);
+static const struct atNBPtuple *nbp_name_print(const struct atNBPtuple *,
+                                              const u_char *);
+static const char *ataddr_string(u_short, u_char);
+static void ddp_print(const u_char *, u_int, int, u_short, u_char, u_char);
+static const char *ddpskt_string(int);
+
+/*
+ * Print AppleTalk Datagram Delivery Protocol packets.
+ */
+void
+atalk_print(register const u_char *bp, u_int length)
+{
+       register const struct LAP *lp;
+       register const struct atDDP *dp;
+       register const struct atShortDDP *sdp;
+       u_short snet;
+
+       lp = (struct LAP *)bp;
+       bp += sizeof(*lp);
+       length -= sizeof(*lp);
+       switch (lp->type) {
+
+       case lapShortDDP:
+               if (length < ddpSSize) {
+                       (void)printf(" [|sddp %d]", length);
+                       return;
+               }
+               sdp = (const struct atShortDDP *)bp;
+               printf("%s.%s",
+                   ataddr_string(0, lp->src), ddpskt_string(sdp->srcSkt));
+               printf(" > %s.%s:",
+                   ataddr_string(0, lp->dst), ddpskt_string(sdp->dstSkt));
+               bp += ddpSSize;
+               length -= ddpSSize;
+               ddp_print(bp, length, sdp->type, 0, lp->src, sdp->srcSkt);
+               break;
+
+       case lapDDP:
+               if (length < ddpSize) {
+                       (void)printf(" [|ddp %d]", length);
+                       return;
+               }
+               dp = (const struct atDDP *)bp;
+               snet = EXTRACT_16BITS(&dp->srcNet);
+               printf("%s.%s", ataddr_string(snet, dp->srcNode),
+                   ddpskt_string(dp->srcSkt));
+               printf(" > %s.%s:",
+                   ataddr_string(EXTRACT_16BITS(&dp->dstNet), dp->dstNode),
+                   ddpskt_string(dp->dstSkt));
+               bp += ddpSize;
+               length -= ddpSize;
+               ddp_print(bp, length, dp->type, snet, dp->srcNode, dp->srcSkt);
+               break;
+
+#ifdef notdef
+       case lapKLAP:
+               klap_print(bp, length);
+               break;
+#endif
+
+       default:
+               printf("%d > %d at-lap#%d %d",
+                   lp->src, lp->dst, lp->type, length);
+               break;
+       }
+}
+
+/* XXX should probably pass in the snap header and do checks like arp_print() */
+void
+aarp_print(register const u_char *bp, u_int length)
+{
+       register const struct aarp *ap;
+
+#define AT(member) ataddr_string((ap->member[1]<<8)|ap->member[2],ap->member[3])
+
+       printf("aarp ");
+       ap = (const struct aarp *)bp;
+       if (ap->htype == 1 && ap->ptype == ETHERTYPE_ATALK &&
+           ap->halen == 6 && ap->palen == 4 )
+               switch (ap->op) {
+
+               case 1:                         /* request */
+                       (void)printf("who-has %s tell %s",
+                           AT(pdaddr), AT(psaddr));
+                       return;
+
+               case 2:                         /* response */
+                       (void)printf("reply %s is-at %s",
+                           AT(pdaddr), etheraddr_string(ap->hdaddr));
+                       return;
+
+               case 3:                         /* probe (oy!) */
+                       (void)printf("probe %s tell %s",
+                           AT(pdaddr), AT(psaddr));
+                       return;
+               }
+       (void)printf("len %d op %d htype %d ptype %#x halen %d palen %d",
+           length, ap->op, ap->htype, ap->ptype, ap->halen, ap->palen );
+}
+
+static void
+ddp_print(register const u_char *bp, register u_int length, register int t,
+         register u_short snet, register u_char snode, u_char skt)
+{
+
+       switch (t) {
+
+       case ddpNBP:
+               nbp_print((const struct atNBP *)bp, length, snet, snode, skt);
+               break;
+
+       case ddpATP:
+               atp_print((const struct atATP *)bp, length);
+               break;
+
+       default:
+               (void)printf(" at-%s %d", tok2str(type2str, NULL, t), length);
+               break;
+       }
+}
+
+static void
+atp_print(register const struct atATP *ap, u_int length)
+{
+       char c;
+       u_int32_t data;
+
+       if ((const u_char *)(ap + 1) > snapend) {
+               /* Just bail if we don't have the whole chunk. */
+               fputs(tstr, stdout);
+               return;
+       }
+       length -= sizeof(*ap);
+       switch (ap->control & 0xc0) {
+
+       case atpReqCode:
+               (void)printf(" atp-req%s %d",
+                            ap->control & atpXO? " " : "*",
+                            EXTRACT_16BITS(&ap->transID));
+
+               atp_bitmap_print(ap->bitmap);
+
+               if (length != 0)
+                       (void)printf(" [len=%d]", length);
+
+               switch (ap->control & (atpEOM|atpSTS)) {
+               case atpEOM:
+                       (void)printf(" [EOM]");
+                       break;
+               case atpSTS:
+                       (void)printf(" [STS]");
+                       break;
+               case atpEOM|atpSTS:
+                       (void)printf(" [EOM,STS]");
+                       break;
+               }
+               break;
+
+       case atpRspCode:
+               (void)printf(" atp-resp%s%d:%d (%d)",
+                            ap->control & atpEOM? "*" : " ",
+                            EXTRACT_16BITS(&ap->transID), ap->bitmap, length);
+               switch (ap->control & (atpXO|atpSTS)) {
+               case atpXO:
+                       (void)printf(" [XO]");
+                       break;
+               case atpSTS:
+                       (void)printf(" [STS]");
+                       break;
+               case atpXO|atpSTS:
+                       (void)printf(" [XO,STS]");
+                       break;
+               }
+               break;
+
+       case atpRelCode:
+               (void)printf(" atp-rel  %d", EXTRACT_16BITS(&ap->transID));
+
+               atp_bitmap_print(ap->bitmap);
+
+               /* length should be zero */
+               if (length)
+                       (void)printf(" [len=%d]", length);
+
+               /* there shouldn't be any control flags */
+               if (ap->control & (atpXO|atpEOM|atpSTS)) {
+                       c = '[';
+                       if (ap->control & atpXO) {
+                               (void)printf("%cXO", c);
+                               c = ',';
+                       }
+                       if (ap->control & atpEOM) {
+                               (void)printf("%cEOM", c);
+                               c = ',';
+                       }
+                       if (ap->control & atpSTS) {
+                               (void)printf("%cSTS", c);
+                               c = ',';
+                       }
+                       (void)printf("]");
+               }
+               break;
+
+       default:
+               (void)printf(" atp-0x%x  %d (%d)", ap->control,
+                            EXTRACT_16BITS(&ap->transID), length);
+               break;
+       }
+       data = EXTRACT_32BITS(&ap->userData);
+       if (data != 0)
+               (void)printf(" 0x%x", data);
+}
+
+static void
+atp_bitmap_print(register u_char bm)
+{
+       register char c;
+       register int i;
+
+       /*
+        * The '& 0xff' below is needed for compilers that want to sign
+        * extend a u_char, which is the case with the Ultrix compiler.
+        * (gcc is smart enough to eliminate it, at least on the Sparc).
+        */
+       if ((bm + 1) & (bm & 0xff)) {
+               c = '<';
+               for (i = 0; bm; ++i) {
+                       if (bm & 1) {
+                               (void)printf("%c%d", c, i);
+                               c = ',';
+                       }
+                       bm >>= 1;
+               }
+               (void)printf(">");
+       } else {
+               for (i = 0; bm; ++i)
+                       bm >>= 1;
+               if (i > 1)
+                       (void)printf("<0-%d>", i - 1);
+               else
+                       (void)printf("<0>");
+       }
+}
+
+static void
+nbp_print(register const struct atNBP *np, u_int length, register u_short snet,
+         register u_char snode, register u_char skt)
+{
+       register const struct atNBPtuple *tp =
+                       (struct atNBPtuple *)((u_char *)np + nbpHeaderSize);
+       int i;
+       const u_char *ep;
+
+       length -= nbpHeaderSize;
+       if (length < 8) {
+               /* must be room for at least one tuple */
+               (void)printf(" truncated-nbp %d", length + nbpHeaderSize);
+               return;
+       }
+       /* ep points to end of available data */
+       ep = snapend;
+       if ((const u_char *)tp > ep) {
+               fputs(tstr, stdout);
+               return;
+       }
+       switch (i = np->control & 0xf0) {
+
+       case nbpBrRq:
+       case nbpLkUp:
+               (void)printf(i == nbpLkUp? " nbp-lkup %d:":" nbp-brRq %d:",
+                            np->id);
+               if ((const u_char *)(tp + 1) > ep) {
+                       fputs(tstr, stdout);
+                       return;
+               }
+               (void)nbp_name_print(tp, ep);
+               /*
+                * look for anomalies: the spec says there can only
+                * be one tuple, the address must match the source
+                * address and the enumerator should be zero.
+                */
+               if ((np->control & 0xf) != 1)
+                       (void)printf(" [ntup=%d]", np->control & 0xf);
+               if (tp->enumerator)
+                       (void)printf(" [enum=%d]", tp->enumerator);
+               if (EXTRACT_16BITS(&tp->net) != snet ||
+                   tp->node != snode || tp->skt != skt)
+                       (void)printf(" [addr=%s.%d]",
+                           ataddr_string(EXTRACT_16BITS(&tp->net),
+                           tp->node), tp->skt);
+               break;
+
+       case nbpLkUpReply:
+               (void)printf(" nbp-reply %d:", np->id);
+
+               /* print each of the tuples in the reply */
+               for (i = np->control & 0xf; --i >= 0 && tp; )
+                       tp = nbp_tuple_print(tp, ep, snet, snode, skt);
+               break;
+
+       default:
+               (void)printf(" nbp-0x%x  %d (%d)", np->control, np->id,
+                               length);
+               break;
+       }
+}
+
+/* print a counted string */
+static const char *
+print_cstring(register const char *cp, register const u_char *ep)
+{
+       register u_int length;
+
+       if (cp >= (const char *)ep) {
+               fputs(tstr, stdout);
+               return (0);
+       }
+       length = *cp++;
+
+       /* Spec says string can be at most 32 bytes long */
+       if (length < 0 || length > 32) {
+               (void)printf("[len=%d]", length);
+               return (0);
+       }
+       while (--length >= 0) {
+               if (cp >= (char *)ep) {
+                       fputs(tstr, stdout);
+                       return (0);
+               }
+               putchar(*cp++);
+       }
+       return (cp);
+}
+
+static const struct atNBPtuple *
+nbp_tuple_print(register const struct atNBPtuple *tp,
+               register const u_char *ep,
+               register u_short snet, register u_char snode,
+               register u_char skt)
+{
+       register const struct atNBPtuple *tpn;
+
+       if ((const u_char *)(tp + 1) > ep) {
+               fputs(tstr, stdout);
+               return 0;
+       }
+       tpn = nbp_name_print(tp, ep);
+
+       /* if the enumerator isn't 1, print it */
+       if (tp->enumerator != 1)
+               (void)printf("(%d)", tp->enumerator);
+
+       /* if the socket doesn't match the src socket, print it */
+       if (tp->skt != skt)
+               (void)printf(" %d", tp->skt);
+
+       /* if the address doesn't match the src address, it's an anomaly */
+       if (EXTRACT_16BITS(&tp->net) != snet || tp->node != snode)
+               (void)printf(" [addr=%s]",
+                   ataddr_string(EXTRACT_16BITS(&tp->net), tp->node));
+
+       return (tpn);
+}
+
+static const struct atNBPtuple *
+nbp_name_print(const struct atNBPtuple *tp, register const u_char *ep)
+{
+       register const char *cp = (const char *)tp + nbpTupleSize;
+
+       putchar(' ');
+
+       /* Object */
+       putchar('"');
+       if ((cp = print_cstring(cp, ep)) != NULL) {
+               /* Type */
+               putchar(':');
+               if ((cp = print_cstring(cp, ep)) != NULL) {
+                       /* Zone */
+                       putchar('@');
+                       if ((cp = print_cstring(cp, ep)) != NULL)
+                               putchar('"');
+               }
+       }
+       return ((const struct atNBPtuple *)cp);
+}
+
+
+#define HASHNAMESIZE 4096
+
+struct hnamemem {
+       int addr;
+       char *name;
+       struct hnamemem *nxt;
+};
+
+static struct hnamemem hnametable[HASHNAMESIZE];
+
+static const char *
+ataddr_string(u_short atnet, u_char athost)
+{
+       register struct hnamemem *tp, *tp2;
+       register int i = (atnet << 8) | athost;
+       char nambuf[256];
+       static int first = 1;
+       FILE *fp;
+
+       /*
+        * if this is the first call, see if there's an AppleTalk
+        * number to name map file.
+        */
+       if (first && (first = 0, !nflag)
+           && (fp = fopen("/etc/atalk.names", "r"))) {
+               char line[256];
+               int i1, i2, i3;
+
+               while (fgets(line, sizeof(line), fp)) {
+                       if (line[0] == '\n' || line[0] == 0 || line[0] == '#')
+                               continue;
+                       if (sscanf(line, "%d.%d.%d %s", &i1, &i2, &i3,
+                                    nambuf) == 4)
+                               /* got a hostname. */
+                               i3 |= ((i1 << 8) | i2) << 8;
+                       else if (sscanf(line, "%d.%d %s", &i1, &i2,
+                                       nambuf) == 3)
+                               /* got a net name */
+                               i3 = (((i1 << 8) | i2) << 8) | 255;
+                       else
+                               continue;
+
+                       for (tp = &hnametable[i3 & (HASHNAMESIZE-1)];
+                            tp->nxt; tp = tp->nxt)
+                               ;
+                       tp->addr = i3;
+                       tp->nxt = newhnamemem();
+                       tp->name = savestr(nambuf);
+               }
+               fclose(fp);
+       }
+
+       for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
+               if (tp->addr == i)
+                       return (tp->name);
+
+       /* didn't have the node name -- see if we've got the net name */
+       i |= 255;
+       for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt)
+               if (tp2->addr == i) {
+                       tp->addr = (atnet << 8) | athost;
+                       tp->nxt = newhnamemem();
+                       (void)sprintf(nambuf, "%s.%d", tp2->name, athost);
+                       tp->name = savestr(nambuf);
+                       return (tp->name);
+               }
+
+       tp->addr = (atnet << 8) | athost;
+       tp->nxt = newhnamemem();
+       if (athost != 255)
+               (void)sprintf(nambuf, "%d.%d.%d",
+                   atnet >> 8, atnet & 0xff, athost);
+       else
+               (void)sprintf(nambuf, "%d.%d", atnet >> 8, atnet & 0xff);
+       tp->name = savestr(nambuf);
+
+       return (tp->name);
+}
+
+static struct tok skt2str[] = {
+       { rtmpSkt,      "rtmp" },       /* routing table maintenance */
+       { nbpSkt,       "nis" },        /* name info socket */
+       { echoSkt,      "echo" },       /* AppleTalk echo protocol */
+       { zipSkt,       "zip" },        /* zone info protocol */
+       { 0,            NULL }
+};
+
+static const char *
+ddpskt_string(register int skt)
+{
+       static char buf[8];
+
+       if (nflag) {
+               (void)sprintf(buf, "%d", skt);
+               return (buf);
+       }
+       return (tok2str(skt2str, "%d", skt));
+}
diff --git a/tcpdump.tproj/print-atm.c b/tcpdump.tproj/print-atm.c
new file mode 100644 (file)
index 0000000..4abe2ad
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-atm.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <pcap.h>
+
+#include "addrtoname.h"
+#include "ethertype.h"
+#include "interface.h"
+
+/*
+ * This is the top level routine of the printer.  'p' is the points
+ * to the LLC/SNAP header of the packet, 'tvp' is the timestamp,
+ * 'length' is the length of the packet off the wire, and 'caplen'
+ * is the number of bytes actually captured.
+ */
+void
+atm_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       u_int caplen = h->caplen;
+       u_int length = h->len;
+       u_short ethertype;
+
+       ts_print(&h->ts);
+
+       if (caplen < 8) {
+               printf("[|atm]");
+               goto out;
+       }
+       if (p[0] != 0xaa || p[1] != 0xaa || p[2] != 0x03) {
+               /*XXX assume 802.6 MAC header from fore driver */
+               if (eflag)
+                       printf("%04x%04x %04x%04x ",
+                              p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3],
+                              p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7],
+                              p[8] << 24 | p[9] << 16 | p[10] << 8 | p[11],
+                              p[12] << 24 | p[13] << 16 | p[14] << 8 | p[15]);
+               p += 20;
+               length -= 20;
+               caplen -= 20;
+       }
+       ethertype = p[6] << 8 | p[7];
+       if (eflag)
+               printf("%02x %02x %02x %02x-%02x-%02x %04x: ",
+                      p[0], p[1], p[2], /* dsap/ssap/ctrl */
+                      p[3], p[4], p[5], /* manufacturer's code */
+                      ethertype);
+
+       /*
+        * Some printers want to get back at the ethernet addresses,
+        * and/or check that they're not walking off the end of the packet.
+        * Rather than pass them all the way down, we set these globals.
+        */
+       packetp = p;
+       snapend = p + caplen;
+
+       length -= 8;
+       caplen -= 8;
+       p += 8;
+
+       switch (ethertype) {
+
+       case ETHERTYPE_IP:
+               ip_print(p, length);
+               break;
+
+               /*XXX this probably isn't right */
+       case ETHERTYPE_ARP:
+       case ETHERTYPE_REVARP:
+               arp_print(p, length, caplen);
+               break;
+#ifdef notyet
+       case ETHERTYPE_DN:
+               decnet_print(p, length, caplen);
+               break;
+
+       case ETHERTYPE_ATALK:
+               if (vflag)
+                       fputs("et1 ", stdout);
+               atalk_print(p, length);
+               break;
+
+       case ETHERTYPE_AARP:
+               aarp_print(p, length);
+               break;
+
+       case ETHERTYPE_LAT:
+       case ETHERTYPE_MOPRC:
+       case ETHERTYPE_MOPDL:
+               /* default_print for now */
+#endif
+       default:
+               /* ether_type not known, print raw packet */
+               if (!eflag)
+                       printf("%02x %02x %02x %02x-%02x-%02x %04x: ",
+                              p[0], p[1], p[2], /* dsap/ssap/ctrl */
+                              p[3], p[4], p[5], /* manufacturer's code */
+                              ethertype);
+               if (!xflag && !qflag)
+                       default_print(p, caplen);
+       }
+       if (xflag)
+               default_print(p, caplen);
+ out:
+       putchar('\n');
+}
diff --git a/tcpdump.tproj/print-bootp.c b/tcpdump.tproj/print-bootp.c
new file mode 100644 (file)
index 0000000..c938728
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print bootp packets.
+ */
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-bootp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "bootp.h"
+
+static void rfc1048_print(const u_char *, u_int);
+static void cmu_print(const u_char *, u_int);
+
+static char tstr[] = " [|bootp]";
+
+/*
+ * Print bootp requests
+ */
+void
+bootp_print(register const u_char *cp, u_int length,
+           u_short sport, u_short dport)
+{
+       register const struct bootp *bp;
+       static u_char vm_cmu[4] = VM_CMU;
+       static u_char vm_rfc1048[4] = VM_RFC1048;
+
+       bp = (struct bootp *)cp;
+       TCHECK(bp->bp_op);
+       switch (bp->bp_op) {
+
+       case BOOTREQUEST:
+               /* Usually, a request goes from a client to a server */
+               if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
+                       printf(" (request)");
+               break;
+
+       case BOOTREPLY:
+               /* Usually, a reply goes from a server to a client */
+               if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
+                       printf(" (reply)");
+               break;
+
+       default:
+               printf(" bootp-#%d", bp->bp_op);
+       }
+
+       TCHECK(bp->bp_secs);
+
+       /* The usual hardware address type is 1 (10Mb Ethernet) */
+       if (bp->bp_htype != 1)
+               printf(" htype-#%d", bp->bp_htype);
+
+       /* The usual length for 10Mb Ethernet address is 6 bytes */
+       if (bp->bp_htype != 1 || bp->bp_hlen != 6)
+               printf(" hlen:%d", bp->bp_hlen);
+
+       /* Only print interesting fields */
+       if (bp->bp_hops)
+               printf(" hops:%d", bp->bp_hops);
+       if (bp->bp_xid)
+               printf(" xid:0x%x", (u_int32_t)ntohl(bp->bp_xid));
+       if (bp->bp_secs)
+               printf(" secs:%d", ntohs(bp->bp_secs));
+
+       /* Client's ip address */
+       TCHECK(bp->bp_ciaddr);
+       if (bp->bp_ciaddr.s_addr)
+               printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
+
+       /* 'your' ip address (bootp client) */
+       TCHECK(bp->bp_yiaddr);
+       if (bp->bp_yiaddr.s_addr)
+               printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
+
+       /* Server's ip address */
+       TCHECK(bp->bp_siaddr);
+       if (bp->bp_siaddr.s_addr)
+               printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
+
+       /* Gateway's ip address */
+       TCHECK(bp->bp_giaddr);
+       if (bp->bp_giaddr.s_addr)
+               printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
+
+       /* Client's Ethernet address */
+       if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
+               register const struct ether_header *eh;
+               register const char *e;
+
+               TCHECK2(bp->bp_chaddr[0], 6);
+               eh = (struct ether_header *)packetp;
+               if (bp->bp_op == BOOTREQUEST)
+                       e = (const char *)ESRC(eh);
+               else if (bp->bp_op == BOOTREPLY)
+                       e = (const char *)EDST(eh);
+               else
+                       e = 0;
+               if (e == 0 || memcmp((char *)bp->bp_chaddr, e, 6) != 0)
+                       printf(" ether %s", etheraddr_string(bp->bp_chaddr));
+       }
+
+       TCHECK2(bp->bp_sname[0], 1);            /* check first char only */
+       if (*bp->bp_sname) {
+               printf(" sname \"");
+               if (fn_print(bp->bp_sname, snapend)) {
+                       putchar('"');
+                       fputs(tstr + 1, stdout);
+                       return;
+               }
+       }
+       TCHECK2(bp->bp_sname[0], 1);            /* check first char only */
+       if (*bp->bp_file) {
+               printf(" file \"");
+               if (fn_print(bp->bp_file, snapend)) {
+                       putchar('"');
+                       fputs(tstr + 1, stdout);
+                       return;
+               }
+       }
+
+       /* Decode the vendor buffer */
+       TCHECK(bp->bp_vend[0]);
+       length -= sizeof(*bp) - sizeof(bp->bp_vend);
+       if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048,
+                sizeof(u_int32_t)) == 0)
+               rfc1048_print(bp->bp_vend, length);
+       else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu,
+                     sizeof(u_int32_t)) == 0)
+               cmu_print(bp->bp_vend, length);
+       else {
+               u_int32_t ul;
+
+               memcpy((char *)&ul, (char *)bp->bp_vend, sizeof(ul));
+               if (ul != 0)
+                       printf("vend-#0x%x", ul);
+       }
+
+       return;
+trunc:
+       fputs(tstr, stdout);
+}
+
+/* The first character specifies the format to print */
+static struct tok tag2str[] = {
+/* RFC1048 tags */
+       { TAG_PAD,              " PAD" },
+       { TAG_SUBNET_MASK,      "iSM" },        /* subnet mask (RFC950) */
+       { TAG_TIME_OFFSET,      "lTZ" },        /* seconds from UTC */
+       { TAG_GATEWAY,          "iDG" },        /* default gateway */
+       { TAG_TIME_SERVER,      "iTS" },        /* time servers (RFC868) */
+       { TAG_NAME_SERVER,      "iIEN" },       /* IEN name servers (IEN116) */
+       { TAG_DOMAIN_SERVER,    "iNS" },        /* domain name (RFC1035) */
+       { TAG_LOG_SERVER,       "iLOG" },       /* MIT log servers */
+       { TAG_COOKIE_SERVER,    "iCS" },        /* cookie servers (RFC865) */
+       { TAG_LPR_SERVER,       "iLPR" },       /* lpr server (RFC1179) */
+       { TAG_IMPRESS_SERVER,   "iIM" },        /* impress servers (Imagen) */
+       { TAG_RLP_SERVER,       "iRL" },        /* resource location (RFC887) */
+       { TAG_HOSTNAME,         "aHN" },        /* ascii hostname */
+       { TAG_BOOTSIZE,         "sBS" },        /* 512 byte blocks */
+       { TAG_END,              " END" },
+/* RFC1497 tags */
+       { TAG_DUMPPATH,         "aDP" },
+       { TAG_DOMAINNAME,       "aDN" },
+       { TAG_SWAP_SERVER,      "iSS" },
+       { TAG_ROOTPATH,         "aRP" },
+       { TAG_EXTPATH,          "aEP" },
+       { 0,                    NULL }
+};
+
+static void
+rfc1048_print(register const u_char *bp, register u_int length)
+{
+       register u_char tag;
+       register u_int len, size;
+       register const char *cp;
+       register char c;
+       int first;
+       u_int32_t ul;
+       u_short us;
+
+       printf(" vend-rfc1048");
+
+       /* Step over magic cookie */
+       bp += sizeof(int32_t);
+
+       /* Loop while we there is a tag left in the buffer */
+       while (bp + 1 < snapend) {
+               tag = *bp++;
+               if (tag == TAG_PAD)
+                       continue;
+               if (tag == TAG_END)
+                       return;
+               cp = tok2str(tag2str, "?T%d", tag);
+               c = *cp++;
+               printf(" %s:", cp);
+
+               /* Get the length; check for truncation */
+               if (bp + 1 >= snapend) {
+                       fputs(tstr, stdout);
+                       return;
+               }
+               len = *bp++;
+               if (bp + len >= snapend) {
+                       fputs(tstr, stdout);
+                       return;
+               }
+
+               /* Print data */
+               size = len;
+               if (c == '?') {
+                       /* Base default formats for unknown tags on data size */
+                       if (size & 1)
+                               c = 'b';
+                       else if (size & 2)
+                               c = 's';
+                       else
+                               c = 'l';
+               }
+               first = 1;
+               switch (c) {
+
+               case 'a':
+                       /* ascii strings */
+                       putchar('"');
+                       (void)fn_printn(bp, size, NULL);
+                       putchar('"');
+                       bp += size;
+                       size = 0;
+                       break;
+
+               case 'i':
+               case 'l':
+                       /* ip addresses/32-bit words */
+                       while (size >= sizeof(ul)) {
+                               if (!first)
+                                       putchar(',');
+                               memcpy((char *)&ul, (char *)bp, sizeof(ul));
+                               if (c == 'i')
+                                       printf("%s", ipaddr_string(&ul));
+                               else
+                                       printf("%u", ul);
+                               bp += sizeof(ul);
+                               size -= sizeof(ul);
+                               first = 0;
+                       }
+                       break;
+
+               case 's':
+                       /* shorts */
+                       while (size >= sizeof(us)) {
+                               if (!first)
+                                       putchar(',');
+                               memcpy((char *)&us, (char *)bp, sizeof(us));
+                               printf("%d", us);
+                               bp += sizeof(us);
+                               size -= sizeof(us);
+                               first = 0;
+                       }
+                       break;
+
+               case 'b':
+               default:
+                       /* Bytes */
+                       while (size > 0) {
+                               if (!first)
+                                       putchar('.');
+                               printf("%d", *bp);
+                               ++bp;
+                               --size;
+                               first = 0;
+                       }
+                       break;
+               }
+               /* Data left over? */
+               if (size)
+                       printf("[len %d]", len);
+       }
+}
+
+static void
+cmu_print(register const u_char *bp, register u_int length)
+{
+       register const struct cmu_vend *cmu;
+       char *fmt = " %s:%s";
+
+#define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \
+    if (cmu->m.s_addr != 0) \
+       printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); }
+
+       printf(" vend-cmu");
+       cmu = (struct cmu_vend *)bp;
+
+       /* Only print if there are unknown bits */
+       TCHECK(cmu->v_flags);
+       if ((cmu->v_flags & ~(VF_SMASK)) != 0)
+               printf(" F:0x%x", cmu->v_flags);
+       PRINTCMUADDR(v_dgate, "DG");
+       PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*");
+       PRINTCMUADDR(v_dns1, "NS1");
+       PRINTCMUADDR(v_dns2, "NS2");
+       PRINTCMUADDR(v_ins1, "IEN1");
+       PRINTCMUADDR(v_ins2, "IEN2");
+       PRINTCMUADDR(v_ts1, "TS1");
+       PRINTCMUADDR(v_ts2, "TS2");
+       return;
+
+trunc:
+       fputs(tstr, stdout);
+#undef PRINTCMUADDR
+}
diff --git a/tcpdump.tproj/print-decnet.c b/tcpdump.tproj/print-decnet.c
new file mode 100644 (file)
index 0000000..a65152e
--- /dev/null
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-decnet.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#ifdef HAVE_LIBDNET
+#include <netdnet/dnetdb.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "decnet.h"
+#include "extract.h"
+#include "interface.h"
+#include "addrtoname.h"
+
+/* Forwards */
+static void print_decnet_ctlmsg(const union routehdr *, u_int);
+static void print_t_info(int);
+static void print_l1_routes(const char *, u_int);
+static void print_l2_routes(const char *, u_int);
+static void print_i_info(int);
+static void print_elist(const char *, u_int);
+static void print_nsp(const u_char *, u_int);
+static void print_reason(int);
+#ifdef PRINT_NSPDATA
+static void pdata(u_char *, int);
+#endif
+
+#ifdef HAVE_LIBDNET
+extern char *dnet_htoa(struct dn_naddr *);
+#endif
+
+void
+decnet_print(register const u_char *ap, register u_int length,
+            register u_int caplen)
+{
+       static union routehdr rhcopy;
+       register union routehdr *rhp = &rhcopy;
+       register int mflags;
+       int dst, src, hops;
+       u_int rhlen, nsplen, pktlen;
+       const u_char *nspp;
+
+       if (length < sizeof(struct shorthdr)) {
+               (void)printf("[|decnet]");
+               return;
+       }
+
+       pktlen = EXTRACT_LE_16BITS(ap);
+
+       rhlen = min(length, caplen);
+       rhlen = min(rhlen, sizeof(*rhp));
+       memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
+
+       mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
+
+       if (mflags & RMF_PAD) {
+           /* pad bytes of some sort in front of message */
+           u_int padlen = mflags & RMF_PADMASK;
+           if (vflag)
+               (void) printf("[pad:%d] ", padlen);
+           ap += padlen;
+           length -= padlen;
+           caplen -= padlen;
+           rhlen = min(length, caplen);
+           rhlen = min(rhlen, sizeof(*rhp));
+           memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
+           mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
+       }
+
+       if (mflags & RMF_FVER) {
+               (void) printf("future-version-decnet");
+               default_print(ap, length);
+               return;
+       }
+
+       /* is it a control message? */
+       if (mflags & RMF_CTLMSG) {
+               print_decnet_ctlmsg(rhp, min(length, caplen));
+               return;
+       }
+
+       switch (mflags & RMF_MASK) {
+       case RMF_LONG:
+           dst =
+               EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr);
+           src =
+               EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr);
+           hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits);
+           nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]);
+           nsplen = min((length - sizeof(struct longhdr)),
+                        (caplen - sizeof(struct longhdr)));
+           break;
+       case RMF_SHORT:
+           dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst);
+           src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src);
+           hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1;
+           nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]);
+           nsplen = min((length - sizeof(struct shorthdr)),
+                        (caplen - sizeof(struct shorthdr)));
+           break;
+       default:
+           (void) printf("unknown message flags under mask");
+           default_print((u_char *)ap, length);
+           return;
+       }
+
+       (void)printf("%s > %s %d ",
+                       dnaddr_string(src), dnaddr_string(dst), pktlen);
+       if (vflag) {
+           if (mflags & RMF_RQR)
+               (void)printf("RQR ");
+           if (mflags & RMF_RTS)
+               (void)printf("RTS ");
+           if (mflags & RMF_IE)
+               (void)printf("IE ");
+           (void)printf("%d hops ", hops);
+       }
+
+       print_nsp(nspp, nsplen);
+}
+
+static void
+print_decnet_ctlmsg(register const union routehdr *rhp, u_int length)
+{
+       int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
+       register union controlmsg *cmp = (union controlmsg *)rhp;
+       int src, dst, info, blksize, eco, ueco, hello, other, vers;
+       etheraddr srcea, rtea;
+       int priority;
+       char *rhpx = (char *)rhp;
+
+       switch (mflags & RMF_CTLMASK) {
+       case RMF_INIT:
+           (void)printf("init ");
+           src = EXTRACT_LE_16BITS(cmp->cm_init.in_src);
+           info = EXTRACT_LE_8BITS(cmp->cm_init.in_info);
+           blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize);
+           vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers);
+           eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco);
+           ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco);
+           hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello);
+           print_t_info(info);
+           (void)printf(
+               "src %sblksize %d vers %d eco %d ueco %d hello %d",
+                       dnaddr_string(src), blksize, vers, eco, ueco,
+                       hello);
+           break;
+       case RMF_VER:
+           (void)printf("verification ");
+           src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src);
+           other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval);
+           (void)printf("src %s fcnval %o", dnaddr_string(src), other);
+           break;
+       case RMF_TEST:
+           (void)printf("test ");
+           src = EXTRACT_LE_16BITS(cmp->cm_test.te_src);
+           other = EXTRACT_LE_8BITS(cmp->cm_test.te_data);
+           (void)printf("src %s data %o", dnaddr_string(src), other);
+           break;
+       case RMF_L1ROUT:
+           (void)printf("lev-1-routing ");
+           src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src);
+           (void)printf("src %s ", dnaddr_string(src));
+           print_l1_routes(&(rhpx[sizeof(struct l1rout)]),
+                               length - sizeof(struct l1rout));
+           break;
+       case RMF_L2ROUT:
+           (void)printf("lev-2-routing ");
+           src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src);
+           (void)printf("src %s ", dnaddr_string(src));
+           print_l2_routes(&(rhpx[sizeof(struct l2rout)]),
+                               length - sizeof(struct l2rout));
+           break;
+       case RMF_RHELLO:
+           (void)printf("router-hello ");
+           vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers);
+           eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco);
+           ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco);
+           memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src),
+               sizeof(srcea));
+           src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
+           info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info);
+           blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize);
+           priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority);
+           hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello);
+           print_i_info(info);
+           (void)printf(
+           "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d",
+                       vers, eco, ueco, dnaddr_string(src),
+                       blksize, priority, hello);
+           print_elist(&(rhpx[sizeof(struct rhellomsg)]),
+                               length - sizeof(struct rhellomsg));
+           break;
+       case RMF_EHELLO:
+           (void)printf("endnode-hello ");
+           vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers);
+           eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco);
+           ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco);
+           memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src),
+               sizeof(srcea));
+           src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
+           info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info);
+           blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize);
+           /*seed*/
+           memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router),
+               sizeof(rtea));
+           dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr);
+           hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello);
+           other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data);
+           print_i_info(info);
+           (void)printf(
+       "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o",
+                       vers, eco, ueco, dnaddr_string(src),
+                       blksize, dnaddr_string(dst), hello, other);
+           break;
+
+       default:
+           (void)printf("unknown control message");
+           default_print((u_char *)rhp, length);
+           break;
+       }
+}
+
+static void
+print_t_info(int info)
+{
+       int ntype = info & 3;
+       switch (ntype) {
+       case 0: (void)printf("reserved-ntype? "); break;
+       case TI_L2ROUT: (void)printf("l2rout "); break;
+       case TI_L1ROUT: (void)printf("l1rout "); break;
+       case TI_ENDNODE: (void)printf("endnode "); break;
+       }
+       if (info & TI_VERIF)
+           (void)printf("verif ");
+       if (info & TI_BLOCK)
+           (void)printf("blo ");
+}
+
+static void
+print_l1_routes(const char *rp, u_int len)
+{
+       int count;
+       int id;
+       int info;
+
+       /* The last short is a checksum */
+       while (len > (3 * sizeof(short))) {
+           count = EXTRACT_LE_16BITS(rp);
+           if (count > 1024)
+               return; /* seems to be bogus from here on */
+           rp += sizeof(short);
+           len -= sizeof(short);
+           id = EXTRACT_LE_16BITS(rp);
+           rp += sizeof(short);
+           len -= sizeof(short);
+           info = EXTRACT_LE_16BITS(rp);
+           rp += sizeof(short);
+           len -= sizeof(short);
+           (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count,
+                           RI_COST(info), RI_HOPS(info));
+       }
+}
+
+static void
+print_l2_routes(const char *rp, u_int len)
+{
+       int count;
+       int area;
+       int info;
+
+       /* The last short is a checksum */
+       while (len > (3 * sizeof(short))) {
+           count = EXTRACT_LE_16BITS(rp);
+           if (count > 1024)
+               return; /* seems to be bogus from here on */
+           rp += sizeof(short);
+           len -= sizeof(short);
+           area = EXTRACT_LE_16BITS(rp);
+           rp += sizeof(short);
+           len -= sizeof(short);
+           info = EXTRACT_LE_16BITS(rp);
+           rp += sizeof(short);
+           len -= sizeof(short);
+           (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count,
+                           RI_COST(info), RI_HOPS(info));
+       }
+}
+
+static void
+print_i_info(int info)
+{
+       int ntype = info & II_TYPEMASK;
+       switch (ntype) {
+       case 0: (void)printf("reserved-ntype? "); break;
+       case II_L2ROUT: (void)printf("l2rout "); break;
+       case II_L1ROUT: (void)printf("l1rout "); break;
+       case II_ENDNODE: (void)printf("endnode "); break;
+       }
+       if (info & II_VERIF)
+           (void)printf("verif ");
+       if (info & II_NOMCAST)
+           (void)printf("nomcast ");
+       if (info & II_BLOCK)
+           (void)printf("blo ");
+}
+
+static void
+print_elist(const char *elp, u_int len)
+{
+       /* Not enough examples available for me to debug this */
+}
+
+static void
+print_nsp(const u_char *nspp, u_int nsplen)
+{
+       const struct nsphdr *nsphp = (struct nsphdr *)nspp;
+       int dst, src, flags;
+
+       flags = EXTRACT_LE_8BITS(nsphp->nh_flags);
+       dst = EXTRACT_LE_16BITS(nsphp->nh_dst);
+       src = EXTRACT_LE_16BITS(nsphp->nh_src);
+
+       switch (flags & NSP_TYPEMASK) {
+       case MFT_DATA:
+           switch (flags & NSP_SUBMASK) {
+           case MFS_BOM:
+           case MFS_MOM:
+           case MFS_EOM:
+           case MFS_BOM+MFS_EOM:
+               printf("data %d>%d ", src, dst);
+               {
+                   struct seghdr *shp = (struct seghdr *)nspp;
+                   int ack;
+#ifdef PRINT_NSPDATA
+                   u_char *dp;
+#endif
+                   u_int data_off = sizeof(struct minseghdr);
+
+                   ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
+                   if (ack & SGQ_ACK) {        /* acknum field */
+                       if ((ack & SGQ_NAK) == SGQ_NAK)
+                           (void)printf("nak %d ", ack & SGQ_MASK);
+                       else
+                           (void)printf("ack %d ", ack & SGQ_MASK);
+                       ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
+                       data_off += sizeof(short);
+                       if (ack & SGQ_OACK) {   /* ackoth field */
+                           if ((ack & SGQ_ONAK) == SGQ_ONAK)
+                               (void)printf("onak %d ", ack & SGQ_MASK);
+                           else
+                               (void)printf("oack %d ", ack & SGQ_MASK);
+                           ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
+                           data_off += sizeof(short);
+                       }
+                   }
+                   (void)printf("seg %d ", ack & SGQ_MASK);
+#ifdef PRINT_NSPDATA
+                   dp = &(nspp[data_off]);
+                   pdata(dp, 10);
+#endif
+               }
+               break;
+           case MFS_ILS+MFS_INT:
+               printf("intr ");
+               {
+                   struct seghdr *shp = (struct seghdr *)nspp;
+                   int ack;
+#ifdef PRINT_NSPDATA
+                   u_char *dp;
+#endif
+                   u_int data_off = sizeof(struct minseghdr);
+
+                   ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
+                   if (ack & SGQ_ACK) {        /* acknum field */
+                       if ((ack & SGQ_NAK) == SGQ_NAK)
+                           (void)printf("nak %d ", ack & SGQ_MASK);
+                       else
+                           (void)printf("ack %d ", ack & SGQ_MASK);
+                       ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
+                       data_off += sizeof(short);
+                       if (ack & SGQ_OACK) {   /* ackdat field */
+                           if ((ack & SGQ_ONAK) == SGQ_ONAK)
+                               (void)printf("nakdat %d ", ack & SGQ_MASK);
+                           else
+                               (void)printf("ackdat %d ", ack & SGQ_MASK);
+                           ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
+                           data_off += sizeof(short);
+                       }
+                   }
+                   (void)printf("seg %d ", ack & SGQ_MASK);
+#ifdef PRINT_NSPDATA
+                   dp = &(nspp[data_off]);
+                   pdata(dp, 10);
+#endif
+               }
+               break;
+           case MFS_ILS:
+               (void)printf("link-service %d>%d ", src, dst);
+               {
+                   struct seghdr *shp = (struct seghdr *)nspp;
+                   struct lsmsg *lsmp =
+                       (struct lsmsg *)&(nspp[sizeof(struct seghdr)]);
+                   int ack;
+                   int lsflags, fcval;
+
+                   ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
+                   if (ack & SGQ_ACK) {        /* acknum field */
+                       if ((ack & SGQ_NAK) == SGQ_NAK)
+                           (void)printf("nak %d ", ack & SGQ_MASK);
+                       else
+                           (void)printf("ack %d ", ack & SGQ_MASK);
+                       ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
+                       if (ack & SGQ_OACK) {   /* ackdat field */
+                           if ((ack & SGQ_ONAK) == SGQ_ONAK)
+                               (void)printf("nakdat %d ", ack & SGQ_MASK);
+                           else
+                               (void)printf("ackdat %d ", ack & SGQ_MASK);
+                           ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
+                       }
+                   }
+                   (void)printf("seg %d ", ack & SGQ_MASK);
+                   lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags);
+                   fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval);
+                   switch (lsflags & LSI_MASK) {
+                   case LSI_DATA:
+                       (void)printf("dat seg count %d ", fcval);
+                       switch (lsflags & LSM_MASK) {
+                       case LSM_NOCHANGE:
+                           break;
+                       case LSM_DONOTSEND:
+                           (void)printf("donotsend-data ");
+                           break;
+                       case LSM_SEND:
+                           (void)printf("send-data ");
+                           break;
+                       default:
+                           (void)printf("reserved-fcmod? %x", lsflags);
+                           break;
+                       }
+                       break;
+                   case LSI_INTR:
+                       (void)printf("intr req count %d ", fcval);
+                       break;
+                   default:
+                       (void)printf("reserved-fcval-int? %x", lsflags);
+                       break;
+                   }
+               }
+               break;
+           default:
+               (void)printf("reserved-subtype? %x %d > %d", flags, src, dst);
+               break;
+           }
+           break;
+       case MFT_ACK:
+           switch (flags & NSP_SUBMASK) {
+           case MFS_DACK:
+               (void)printf("data-ack %d>%d ", src, dst);
+               {
+                   struct ackmsg *amp = (struct ackmsg *)nspp;
+                   int ack;
+
+                   ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
+                   if (ack & SGQ_ACK) {        /* acknum field */
+                       if ((ack & SGQ_NAK) == SGQ_NAK)
+                           (void)printf("nak %d ", ack & SGQ_MASK);
+                       else
+                           (void)printf("ack %d ", ack & SGQ_MASK);
+                       ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
+                       if (ack & SGQ_OACK) {   /* ackoth field */
+                           if ((ack & SGQ_ONAK) == SGQ_ONAK)
+                               (void)printf("onak %d ", ack & SGQ_MASK);
+                           else
+                               (void)printf("oack %d ", ack & SGQ_MASK);
+                       }
+                   }
+               }
+               break;
+           case MFS_IACK:
+               (void)printf("ils-ack %d>%d ", src, dst);
+               {
+                   struct ackmsg *amp = (struct ackmsg *)nspp;
+                   int ack;
+
+                   ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
+                   if (ack & SGQ_ACK) {        /* acknum field */
+                       if ((ack & SGQ_NAK) == SGQ_NAK)
+                           (void)printf("nak %d ", ack & SGQ_MASK);
+                       else
+                           (void)printf("ack %d ", ack & SGQ_MASK);
+                       ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
+                       if (ack & SGQ_OACK) {   /* ackdat field */
+                           if ((ack & SGQ_ONAK) == SGQ_ONAK)
+                               (void)printf("nakdat %d ", ack & SGQ_MASK);
+                           else
+                               (void)printf("ackdat %d ", ack & SGQ_MASK);
+                       }
+                   }
+               }
+               break;
+           case MFS_CACK:
+               (void)printf("conn-ack %d", dst);
+               break;
+           default:
+               (void)printf("reserved-acktype? %x %d > %d", flags, src, dst);
+               break;
+           }
+           break;
+       case MFT_CTL:
+           switch (flags & NSP_SUBMASK) {
+           case MFS_CI:
+           case MFS_RCI:
+               if ((flags & NSP_SUBMASK) == MFS_CI)
+                   (void)printf("conn-initiate ");
+               else
+                   (void)printf("retrans-conn-initiate ");
+               (void)printf("%d>%d ", src, dst);
+               {
+                   struct cimsg *cimp = (struct cimsg *)nspp;
+                   int services, info, segsize;
+#ifdef PRINT_NSPDATA
+                   u_char *dp;
+#endif
+
+                   services = EXTRACT_LE_8BITS(cimp->ci_services);
+                   info = EXTRACT_LE_8BITS(cimp->ci_info);
+                   segsize = EXTRACT_LE_16BITS(cimp->ci_segsize);
+
+                   switch (services & COS_MASK) {
+                   case COS_NONE:
+                       break;
+                   case COS_SEGMENT:
+                       (void)printf("seg ");
+                       break;
+                   case COS_MESSAGE:
+                       (void)printf("msg ");
+                       break;
+                   case COS_CRYPTSER:
+                       (void)printf("crypt ");
+                       break;
+                   }
+                   switch (info & COI_MASK) {
+                   case COI_32:
+                       (void)printf("ver 3.2 ");
+                       break;
+                   case COI_31:
+                       (void)printf("ver 3.1 ");
+                       break;
+                   case COI_40:
+                       (void)printf("ver 4.0 ");
+                       break;
+                   case COI_41:
+                       (void)printf("ver 4.1 ");
+                       break;
+                   }
+                   (void)printf("segsize %d ", segsize);
+#ifdef PRINT_NSPDATA
+                   dp = &(nspp[sizeof(struct cimsg)]);
+                   pdata(dp, nsplen - sizeof(struct cimsg));
+#endif
+               }
+               break;
+           case MFS_CC:
+               (void)printf("conn-confirm %d>%d ", src, dst);
+               {
+                   struct ccmsg *ccmp = (struct ccmsg *)nspp;
+                   int services, info;
+                   u_int segsize, optlen;
+#ifdef PRINT_NSPDATA
+                   u_char *dp;
+#endif
+
+                   services = EXTRACT_LE_8BITS(ccmp->cc_services);
+                   info = EXTRACT_LE_8BITS(ccmp->cc_info);
+                   segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize);
+                   optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen);
+
+                   switch (services & COS_MASK) {
+                   case COS_NONE:
+                       break;
+                   case COS_SEGMENT:
+                       (void)printf("seg ");
+                       break;
+                   case COS_MESSAGE:
+                       (void)printf("msg ");
+                       break;
+                   case COS_CRYPTSER:
+                       (void)printf("crypt ");
+                       break;
+                   }
+                   switch (info & COI_MASK) {
+                   case COI_32:
+                       (void)printf("ver 3.2 ");
+                       break;
+                   case COI_31:
+                       (void)printf("ver 3.1 ");
+                       break;
+                   case COI_40:
+                       (void)printf("ver 4.0 ");
+                       break;
+                   case COI_41:
+                       (void)printf("ver 4.1 ");
+                       break;
+                   }
+                   (void)printf("segsize %d ", segsize);
+                   if (optlen) {
+                       (void)printf("optlen %d ", optlen);
+#ifdef PRINT_NSPDATA
+                       optlen = min(optlen, nsplen - sizeof(struct ccmsg));
+                       dp = &(nspp[sizeof(struct ccmsg)]);
+                       pdata(dp, optlen);
+#endif
+                   }
+               }
+               break;
+           case MFS_DI:
+               (void)printf("disconn-initiate %d>%d ", src, dst);
+               {
+                   struct dimsg *dimp = (struct dimsg *)nspp;
+                   int reason;
+                   u_int optlen;
+#ifdef PRINT_NSPDATA
+                   u_char *dp;
+#endif
+
+                   reason = EXTRACT_LE_16BITS(dimp->di_reason);
+                   optlen = EXTRACT_LE_8BITS(dimp->di_optlen);
+
+                   print_reason(reason);
+                   if (optlen) {
+                       (void)printf("optlen %d ", optlen);
+#ifdef PRINT_NSPDATA
+                       optlen = min(optlen, nsplen - sizeof(struct dimsg));
+                       dp = &(nspp[sizeof(struct dimsg)]);
+                       pdata(dp, optlen);
+#endif
+                   }
+               }
+               break;
+           case MFS_DC:
+               (void)printf("disconn-confirm %d>%d ", src, dst);
+               {
+                   struct dcmsg *dcmp = (struct dcmsg *)nspp;
+                   int reason;
+
+                   reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
+
+                   print_reason(reason);
+               }
+               break;
+           default:
+               (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst);
+               break;
+           }
+           break;
+       default:
+           (void)printf("reserved-type? %x %d > %d", flags, src, dst);
+           break;
+       }
+}
+
+static struct tok reason2str[] = {
+       { UC_OBJREJECT,         "object rejected connect" },
+       { UC_RESOURCES,         "insufficient resources" },
+       { UC_NOSUCHNODE,        "unrecognized node name" },
+       { DI_SHUT,              "node is shutting down" },
+       { UC_NOSUCHOBJ,         "unrecognized object" },
+       { UC_INVOBJFORMAT,      "invalid object name format" },
+       { UC_OBJTOOBUSY,        "object too busy" },
+       { DI_PROTOCOL,          "protocol error discovered" },
+       { DI_TPA,               "third party abort" },
+       { UC_USERABORT,         "user abort" },
+       { UC_INVNODEFORMAT,     "invalid node name format" },
+       { UC_LOCALSHUT,         "local node shutting down" },
+       { DI_LOCALRESRC,        "insufficient local resources" },
+       { DI_REMUSERRESRC,      "insufficient remote user resources" },
+       { UC_ACCESSREJECT,      "invalid access control information" },
+       { DI_BADACCNT,          "bad ACCOUNT information" },
+       { UC_NORESPONSE,        "no response from object" },
+       { UC_UNREACHABLE,       "node unreachable" },
+       { DC_NOLINK,            "no link terminate" },
+       { DC_COMPLETE,          "disconnect complete" },
+       { DI_BADIMAGE,          "bad image data in connect" },
+       { DI_SERVMISMATCH,      "cryptographic service mismatch" },
+       { 0,                    NULL }
+};
+
+static void
+print_reason(register int reason)
+{
+       printf("%s ", tok2str(reason2str, "reason-%d", reason));
+}
+
+char *
+dnnum_string(u_short dnaddr)
+{
+       char *str;
+       int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
+       int node = dnaddr & NODEMASK;
+
+       str = (char *)malloc(sizeof("00.0000"));
+       if (str == NULL)
+               error("dnnum_string: malloc");
+       sprintf(str, "%d.%d", area, node);
+       return(str);
+}
+
+char *
+dnname_string(u_short dnaddr)
+{
+#ifdef HAVE_LIBDNET
+       struct dn_naddr dna;
+
+       dna.a_len = sizeof(short);
+       memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short));
+       return (savestr(dnet_htoa(&dna)));
+#else
+       return(dnnum_string(dnaddr));   /* punt */
+#endif
+}
+
+#ifdef PRINT_NSPDATA
+static void
+pdata(u_char *dp, u_int maxlen)
+{
+       char c;
+       u_int x = maxlen;
+
+       while (x-- > 0) {
+           c = *dp++;
+           if (isprint(c))
+               putchar(c);
+           else
+               printf("\\%o", c & 0xFF);
+       }
+}
+#endif
diff --git a/tcpdump.tproj/print-domain.c b/tcpdump.tproj/print-domain.c
new file mode 100644 (file)
index 0000000..c6175ae
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-domain.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#undef NOERROR                                 /* Solaris sucks */
+#undef T_UNSPEC                                        /* SINIX does too */
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"                    /* must come after interface.h */
+
+/* Compatibility */
+#ifndef T_TXT
+#define T_TXT          16              /* text strings */
+#endif
+#ifndef T_RP
+#define T_RP           17              /* responsible person */
+#endif
+#ifndef T_AFSDB
+#define T_AFSDB                18              /* AFS cell database */
+#endif
+#ifndef T_X25
+#define T_X25          19              /* X_25 calling address */
+#endif
+#ifndef T_ISDN
+#define T_ISDN         20              /* ISDN calling address */
+#endif
+#ifndef T_RT
+#define T_RT           21              /* router */
+#endif
+#ifndef T_NSAP
+#define T_NSAP         22              /* NSAP address */
+#endif
+#ifndef T_NSAP_PTR
+#define T_NSAP_PTR     23              /* reverse NSAP lookup (deprecated) */
+#endif
+#ifndef T_SIG
+#define T_SIG          24              /* security signature */
+#endif
+#ifndef T_KEY
+#define T_KEY          25              /* security key */
+#endif
+#ifndef T_PX
+#define T_PX           26              /* X.400 mail mapping */
+#endif
+#ifndef T_GPOS
+#define T_GPOS         27              /* geographical position (withdrawn) */
+#endif
+#ifndef T_AAAA
+#define T_AAAA         28              /* IP6 Address */
+#endif
+#ifndef T_LOC
+#define T_LOC          29              /* Location Information */
+#endif
+
+#ifndef T_UNSPEC
+#define T_UNSPEC       103             /* Unspecified format (binary data) */
+#endif
+#ifndef T_UNSPECA
+#define T_UNSPECA      104             /* "unspecified ascii". Ugly MIT hack */
+#endif
+
+#ifndef C_CHAOS
+#define C_CHAOS                3               /* for chaos net (MIT) */
+#endif
+#ifndef C_HS
+#define C_HS           4               /* for Hesiod name server (MIT) (XXX) */
+#endif
+
+static char *ns_ops[] = {
+       "", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7",
+       " op8", " updataA", " updateD", " updateDA",
+       " updateM", " updateMA", " zoneInit", " zoneRef",
+};
+
+static char *ns_resp[] = {
+       "", " FormErr", " ServFail", " NXDomain",
+       " NotImp", " Refused", " Resp6", " Resp7",
+       " Resp8", " Resp9", " Resp10", " Resp11",
+       " Resp12", " Resp13", " Resp14", " NoChange",
+};
+
+/* skip over a domain name */
+static const u_char *
+ns_nskip(register const u_char *cp, register const u_char *bp)
+{
+       register u_char i;
+
+       if (((i = *cp++) & INDIR_MASK) == INDIR_MASK)
+               return (cp + 1);
+       while (i && cp < snapend) {
+               cp += i;
+               i = *cp++;
+       }
+       return (cp);
+}
+
+/* print a <domain-name> */
+static const u_char *
+ns_nprint(register const u_char *cp, register const u_char *bp)
+{
+       register u_int i;
+       register const u_char *rp;
+       register int compress;
+
+       i = *cp++;
+       rp = cp + i;
+       if ((i & INDIR_MASK) == INDIR_MASK) {
+               rp = cp + 1;
+               compress = 1;
+       } else
+               compress = 0;
+       if (i != 0)
+               while (i && cp < snapend) {
+                       if ((i & INDIR_MASK) == INDIR_MASK) {
+                               cp = bp + (((i << 8) | *cp) & 0x3fff);
+                               i = *cp++;
+                               continue;
+                       }
+                       if (fn_printn(cp, i, snapend))
+                               break;
+                       cp += i;
+                       putchar('.');
+                       i = *cp++;
+                       if (!compress)
+                               rp += i + 1;
+               }
+       else
+               putchar('.');
+       return (rp);
+}
+
+/* print a <character-string> */
+static const u_char *
+ns_cprint(register const u_char *cp, register const u_char *bp)
+{
+       register u_int i;
+
+       i = *cp++;
+       (void)fn_printn(cp, i, snapend);
+       return (cp + i);
+}
+
+static struct tok type2str[] = {
+       { T_A,          "A" },
+       { T_NS,         "NS" },
+       { T_MD,         "MD" },
+       { T_MF,         "MF" },
+       { T_CNAME,      "CNAME" },
+       { T_SOA,        "SOA" },
+       { T_MB,         "MB" },
+       { T_MG,         "MG" },
+       { T_MR,         "MR" },
+       { T_NULL,       "NULL" },
+       { T_WKS,        "WKS" },
+       { T_PTR,        "PTR" },
+       { T_HINFO,      "HINFO" },
+       { T_MINFO,      "MINFO" },
+       { T_MX,         "MX" },
+       { T_TXT,        "TXT" },
+       { T_RP,         "RP" },
+       { T_AFSDB,      "AFSDB" },
+       { T_X25,        "X25" },
+       { T_ISDN,       "ISDN" },
+       { T_RT,         "RT" },
+       { T_NSAP,       "NSAP" },
+       { T_NSAP_PTR,   "NSAP_PTR" },
+       { T_SIG,        "SIG" },
+       { T_KEY,        "KEY" },
+       { T_PX,         "PX" },
+       { T_GPOS,       "GPOS" },
+       { T_AAAA,       "AAAA" },
+       { T_LOC ,       "LOC " },
+       { T_UINFO,      "UINFO" },
+       { T_UID,        "UID" },
+       { T_GID,        "GID" },
+       { T_UNSPEC,     "UNSPEC" },
+       { T_UNSPECA,    "UNSPECA" },
+       { T_AXFR,       "AXFR" },
+       { T_MAILB,      "MAILB" },
+       { T_MAILA,      "MAILA" },
+       { T_ANY,        "ANY" },
+       { 0,            NULL }
+};
+
+static struct tok class2str[] = {
+       { C_IN,         "IN" },         /* Not used */
+       { C_CHAOS,      "CHAOS)" },
+       { C_HS,         "HS" },
+       { C_ANY,        "ANY" },
+       { 0,            NULL }
+};
+
+/* print a query */
+static void
+ns_qprint(register const u_char *cp, register const u_char *bp)
+{
+       register const u_char *np = cp;
+       register u_int i;
+
+       cp = ns_nskip(cp, bp);
+
+       if (cp + 4 > snapend)
+               return;
+
+       /* print the qtype and qclass (if it's not IN) */
+       i = *cp++ << 8;
+       i |= *cp++;
+       printf(" %s", tok2str(type2str, "Type%d", i));
+       i = *cp++ << 8;
+       i |= *cp++;
+       if (i != C_IN)
+               printf(" %s", tok2str(class2str, "(Class %d)", i));
+
+       fputs("? ", stdout);
+       ns_nprint(np, bp);
+}
+
+/* print a reply */
+static const u_char *
+ns_rprint(register const u_char *cp, register const u_char *bp)
+{
+       register u_int i;
+       register u_short typ, len;
+       register const u_char *rp;
+
+       if (vflag) {
+               putchar(' ');
+               cp = ns_nprint(cp, bp);
+       } else
+               cp = ns_nskip(cp, bp);
+
+       if (cp + 10 > snapend)
+               return (snapend);
+
+       /* print the type/qtype and class (if it's not IN) */
+       typ = *cp++ << 8;
+       typ |= *cp++;
+       i = *cp++ << 8;
+       i |= *cp++;
+       if (i != C_IN)
+               printf(" %s", tok2str(class2str, "(Class %d)", i));
+
+       /* ignore ttl */
+       cp += 4;
+
+       len = *cp++ << 8;
+       len |= *cp++;
+
+       rp = cp + len;
+
+       printf(" %s", tok2str(type2str, "Type%d", typ));
+       switch (typ) {
+
+       case T_A:
+               printf(" %s", ipaddr_string(cp));
+               break;
+
+       case T_NS:
+       case T_CNAME:
+       case T_PTR:
+               putchar(' ');
+               (void)ns_nprint(cp, bp);
+               break;
+
+       case T_MX:
+               putchar(' ');
+               (void)ns_nprint(cp + 2, bp);
+               printf(" %d", EXTRACT_16BITS(cp));
+               break;
+
+       case T_TXT:
+               putchar(' ');
+               (void)ns_cprint(cp, bp);
+               break;
+
+       case T_UNSPECA:         /* One long string */
+               printf(" %.*s", len, cp);
+               break;
+       }
+       return (rp);            /* XXX This isn't always right */
+}
+
+void
+ns_print(register const u_char *bp, u_int length)
+{
+       register const HEADER *np;
+       register int qdcount, ancount, nscount, arcount;
+       register const u_char *cp;
+
+       np = (const HEADER *)bp;
+       /* get the byte-order right */
+       qdcount = ntohs(np->qdcount);
+       ancount = ntohs(np->ancount);
+       nscount = ntohs(np->nscount);
+       arcount = ntohs(np->arcount);
+
+       if (np->qr) {
+               /* this is a response */
+               printf(" %d%s%s%s%s%s",
+                       ntohs(np->id),
+                       ns_ops[np->opcode],
+                       ns_resp[np->rcode],
+                       np->aa? "*" : "",
+                       np->ra? "" : "-",
+                       np->tc? "|" : "");
+               if (qdcount != 1)
+                       printf(" [%dq]", qdcount);
+               /* Print QUESTION section on -vv */
+               if (vflag > 1) {
+                           fputs(" q: ", stdout);
+                           cp = ns_nprint((const u_char *)(np + 1), bp);
+               } else
+                           cp = ns_nskip((const u_char *)(np + 1), bp);
+               printf(" %d/%d/%d", ancount, nscount, arcount);
+               if (ancount--) {
+                       cp = ns_rprint(cp + 4, bp);
+                       while (ancount-- && cp < snapend) {
+                               putchar(',');
+                               cp = ns_rprint(cp, bp);
+                       }
+               }
+       }
+       else {
+               /* this is a request */
+               printf(" %d%s%s",
+                       ntohs(np->id),
+                       ns_ops[np->opcode],
+                       np->rd? "+" : "");
+
+               /* any weirdness? */
+               if (*(((u_short *)np)+1) & htons(0x6ff))
+                       printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1)));
+
+               if (np->opcode == IQUERY) {
+                       if (qdcount)
+                               printf(" [%dq]", qdcount);
+                       if (ancount != 1)
+                               printf(" [%da]", ancount);
+               }
+               else {
+                       if (ancount)
+                               printf(" [%da]", ancount);
+                       if (qdcount != 1)
+                               printf(" [%dq]", qdcount);
+               }
+               if (nscount)
+                       printf(" [%dn]", nscount);
+               if (arcount)
+                       printf(" [%dau]", arcount);
+
+               ns_qprint((const u_char *)(np + 1), (const u_char *)np);
+       }
+       printf(" (%d)", length);
+}
diff --git a/tcpdump.tproj/print-dvmrp.c b/tcpdump.tproj/print-dvmrp.c
new file mode 100644 (file)
index 0000000..a396cf9
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-dvmrp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/*
+ * DVMRP message types and flag values shamelessly stolen from
+ * mrouted/dvmrp.h.
+ */
+#define DVMRP_PROBE            1       /* for finding neighbors */
+#define DVMRP_REPORT           2       /* for reporting some or all routes */
+#define DVMRP_ASK_NEIGHBORS    3       /* sent by mapper, asking for a list */
+                                       /*
+                                        * of this router's neighbors
+                                        */
+#define DVMRP_NEIGHBORS                4       /* response to such a request */
+#define DVMRP_ASK_NEIGHBORS2   5       /* as above, want new format reply */
+#define DVMRP_NEIGHBORS2       6
+#define DVMRP_PRUNE            7       /* prune message */
+#define DVMRP_GRAFT            8       /* graft message */
+#define DVMRP_GRAFT_ACK                9       /* graft acknowledgement */
+
+/*
+ * 'flags' byte values in DVMRP_NEIGHBORS2 reply.
+ */
+#define DVMRP_NF_TUNNEL                0x01    /* neighbors reached via tunnel */
+#define DVMRP_NF_SRCRT         0x02    /* tunnel uses IP source routing */
+#define DVMRP_NF_DOWN          0x10    /* kernel state of interface */
+#define DVMRP_NF_DISABLED      0x20    /* administratively disabled */
+#define DVMRP_NF_QUERIER       0x40    /* I am the subnet's querier */
+
+static void print_probe(const u_char *, const u_char *, u_int);
+static void print_report(const u_char *, const u_char *, u_int);
+static void print_neighbors(const u_char *, const u_char *, u_int);
+static void print_neighbors2(const u_char *, const u_char *, u_int);
+static void print_prune(const u_char *, const u_char *, u_int);
+static void print_graft(const u_char *, const u_char *, u_int);
+static void print_graft_ack(const u_char *, const u_char *, u_int);
+
+static u_int32_t target_level;
+
+void
+dvmrp_print(register const u_char *bp, register u_int len)
+{
+       register const u_char *ep;
+       register u_char type;
+
+       ep = (const u_char *)snapend;
+       if (bp >= ep)
+               return;
+
+       type = bp[1];
+       bp += 8;
+       /*
+        * Skip IGMP header
+        */
+
+       len -= 8;
+
+       switch (type) {
+
+       case DVMRP_PROBE:
+               printf(" Probe");
+               if (vflag)
+                       print_probe(bp, ep, len);
+               break;
+
+       case DVMRP_REPORT:
+               printf(" Report");
+               if (vflag)
+                       print_report(bp, ep, len);
+               break;
+
+       case DVMRP_ASK_NEIGHBORS:
+               printf(" Ask-neighbors(old)");
+               break;
+
+       case DVMRP_NEIGHBORS:
+               printf(" Neighbors(old)");
+               print_neighbors(bp, ep, len);
+               break;
+
+       case DVMRP_ASK_NEIGHBORS2:
+               printf(" Ask-neighbors2");
+               break;
+
+       case DVMRP_NEIGHBORS2:
+               printf(" Neighbors2");
+               /*
+                * extract version and capabilities from IGMP group
+                * address field
+                */
+               bp -= 4;
+               target_level = (bp[0] << 24) | (bp[1] << 16) |
+                   (bp[2] << 8) | bp[3];
+               bp += 4;
+               print_neighbors2(bp, ep, len);
+               break;
+
+       case DVMRP_PRUNE:
+               printf(" Prune");
+               print_prune(bp, ep, len);
+               break;
+
+       case DVMRP_GRAFT:
+               printf(" Graft");
+               print_graft(bp, ep, len);
+               break;
+
+       case DVMRP_GRAFT_ACK:
+               printf(" Graft-ACK");
+               print_graft_ack(bp, ep, len);
+               break;
+
+       default:
+               printf(" [type %d]", type);
+               break;
+       }
+}
+
+static void
+print_report(register const u_char *bp, register const u_char *ep,
+    register u_int len)
+{
+       register u_int32_t mask, origin;
+       register int metric, i, width, done;
+
+       while (len > 0) {
+               if (len < 3) {
+                       printf(" [|]");
+                       return;
+               }
+               mask = (u_int32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2];
+               width = 1;
+               if (bp[0])
+                       width = 2;
+               if (bp[1])
+                       width = 3;
+               if (bp[2])
+                       width = 4;
+
+               printf("\n\tMask %s", intoa(htonl(mask)));
+               bp += 3;
+               len -= 3;
+               do {
+                       if (bp + width + 1 > ep) {
+                               printf(" [|]");
+                               return;
+                       }
+                       if (len < width + 1) {
+                               printf("\n\t  [Truncated Report]");
+                               return;
+                       }
+                       origin = 0;
+                       for (i = 0; i < width; ++i)
+                               origin = origin << 8 | *bp++;
+                       for ( ; i < 4; ++i)
+                               origin <<= 8;
+
+                       metric = *bp++;
+                       done = metric & 0x80;
+                       metric &= 0x7f;
+                       printf("\n\t  %s metric %d", intoa(htonl(origin)),
+                               metric);
+                       len -= width + 1;
+               } while (!done);
+       }
+}
+
+#define GET_ADDR(to) (memcpy((char *)to, (char *)bp, 4), bp += 4)
+
+static void
+print_probe(register const u_char *bp, register const u_char *ep,
+    register u_int len)
+{
+       register u_int32_t genid;
+       u_char neighbor[4];
+
+       if ((len < 4) || ((bp + 4) > ep)) {
+               /* { (ctags) */
+               printf(" [|}");
+               return;
+       }
+       genid = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3];
+       bp += 4;
+       len -= 4;
+       printf("\n\tgenid %u", genid);
+
+       while ((len > 0) && (bp < ep)) {
+               if ((len < 4) || ((bp + 4) > ep)) {
+                       printf(" [|]");
+                       return;
+               }
+               GET_ADDR(neighbor);
+               len -= 4;
+               printf("\n\tneighbor %s", ipaddr_string(neighbor));
+       }
+}
+
+static void
+print_neighbors(register const u_char *bp, register const u_char *ep,
+    register u_int len)
+{
+       u_char laddr[4], neighbor[4];
+       register u_char metric;
+       register u_char thresh;
+       register int ncount;
+
+       while (len > 0 && bp < ep) {
+               if (len < 7 || (bp + 7) >= ep) {
+                       printf(" [|]");
+                       return;
+               }
+               GET_ADDR(laddr);
+               metric = *bp++;
+               thresh = *bp++;
+               ncount = *bp++;
+               len -= 7;
+               while (--ncount >= 0 && (len >= 4) && (bp + 4) < ep) {
+                       GET_ADDR(neighbor);
+                       printf(" [%s ->", ipaddr_string(laddr));
+                       printf(" %s, (%d/%d)]",
+                                  ipaddr_string(neighbor), metric, thresh);
+                       len -= 4;
+               }
+       }
+}
+
+static void
+print_neighbors2(register const u_char *bp, register const u_char *ep,
+    register u_int len)
+{
+       u_char laddr[4], neighbor[4];
+       register u_char metric, thresh, flags;
+       register int ncount;
+
+       printf(" (v %d.%d):",
+              (int)target_level & 0xff,
+              (int)(target_level >> 8) & 0xff);
+
+       while (len > 0 && bp < ep) {
+               if (len < 8 || (bp + 8) >= ep) {
+                       printf(" [|]");
+                       return;
+               }
+               GET_ADDR(laddr);
+               metric = *bp++;
+               thresh = *bp++;
+               flags = *bp++;
+               ncount = *bp++;
+               len -= 8;
+               while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) {
+                       GET_ADDR(neighbor);
+                       printf(" [%s -> ", ipaddr_string(laddr));
+                       printf("%s (%d/%d", ipaddr_string(neighbor),
+                                    metric, thresh);
+                       if (flags & DVMRP_NF_TUNNEL)
+                               printf("/tunnel");
+                       if (flags & DVMRP_NF_SRCRT)
+                               printf("/srcrt");
+                       if (flags & DVMRP_NF_QUERIER)
+                               printf("/querier");
+                       if (flags & DVMRP_NF_DISABLED)
+                               printf("/disabled");
+                       if (flags & DVMRP_NF_DOWN)
+                               printf("/down");
+                       printf(")]");
+                       len -= 4;
+               }
+               if (ncount != -1) {
+                       printf(" [|]");
+                       return;
+               }
+       }
+}
+
+static void
+print_prune(register const u_char *bp, register const u_char *ep,
+    register u_int len)
+{
+       union a {
+               u_char b[4];
+               u_int32_t i;
+       } prune_timer;
+
+       if (len < 12 || (bp + 12) > ep) {
+               printf(" [|]");
+               return;
+       }
+       printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
+       bp += 8;
+       GET_ADDR(prune_timer.b);
+       printf(" timer %d", (int)ntohl(prune_timer.i));
+}
+
+static void
+print_graft(register const u_char *bp, register const u_char *ep,
+    register u_int len)
+{
+
+       if (len < 8 || (bp + 8) > ep) {
+               printf(" [|]");
+               return;
+       }
+       printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
+}
+
+static void
+print_graft_ack(register const u_char *bp, register const u_char *ep,
+    register u_int len)
+{
+
+       if (len < 8 || (bp + 8) > ep) {
+               printf(" [|]");
+               return;
+       }
+       printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
+}
diff --git a/tcpdump.tproj/print-egp.c b/tcpdump.tproj/print-egp.c
new file mode 100644 (file)
index 0000000..092c2b5
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Lawrence Berkeley Laboratory,
+ * Berkeley, CA.  The name of the University may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU).
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-egp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netdb.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+struct egp_packet {
+       u_char  egp_version;
+#define        EGP_VERSION     2
+       u_char  egp_type;
+#define  EGPT_ACQUIRE  3
+#define  EGPT_REACH    5
+#define  EGPT_POLL     2
+#define  EGPT_UPDATE   1
+#define  EGPT_ERROR    8
+       u_char  egp_code;
+#define  EGPC_REQUEST  0
+#define  EGPC_CONFIRM  1
+#define  EGPC_REFUSE   2
+#define  EGPC_CEASE    3
+#define  EGPC_CEASEACK 4
+#define  EGPC_HELLO    0
+#define  EGPC_HEARDU   1
+       u_char  egp_status;
+#define  EGPS_UNSPEC   0
+#define  EGPS_ACTIVE   1
+#define  EGPS_PASSIVE  2
+#define  EGPS_NORES    3
+#define  EGPS_ADMIN    4
+#define  EGPS_GODOWN   5
+#define  EGPS_PARAM    6
+#define  EGPS_PROTO    7
+#define  EGPS_INDET    0
+#define  EGPS_UP       1
+#define  EGPS_DOWN     2
+#define  EGPS_UNSOL    0x80
+       u_short  egp_checksum;
+       u_short  egp_as;
+       u_short  egp_sequence;
+       union {
+               u_short  egpu_hello;
+               u_char egpu_gws[2];
+               u_short  egpu_reason;
+#define  EGPR_UNSPEC   0
+#define  EGPR_BADHEAD  1
+#define  EGPR_BADDATA  2
+#define  EGPR_NOREACH  3
+#define  EGPR_XSPOLL   4
+#define  EGPR_NORESP   5
+#define  EGPR_UVERSION 6
+       } egp_handg;
+#define  egp_hello  egp_handg.egpu_hello
+#define  egp_intgw  egp_handg.egpu_gws[0]
+#define  egp_extgw  egp_handg.egpu_gws[1]
+#define  egp_reason  egp_handg.egpu_reason
+       union {
+               u_short  egpu_poll;
+               u_int32_t egpu_sourcenet;
+       } egp_pands;
+#define  egp_poll  egp_pands.egpu_poll
+#define  egp_sourcenet  egp_pands.egpu_sourcenet
+};
+
+char *egp_acquire_codes[] = {
+       "request",
+       "confirm",
+       "refuse",
+       "cease",
+       "cease_ack"
+};
+
+char *egp_acquire_status[] = {
+       "unspecified",
+       "active_mode",
+       "passive_mode",
+       "insufficient_resources",
+       "administratively_prohibited",
+       "going_down",
+       "parameter_violation",
+       "protocol_violation"
+};
+
+char *egp_reach_codes[] = {
+       "hello",
+       "i-h-u"
+};
+
+char *egp_status_updown[] = {
+       "indeterminate",
+       "up",
+       "down"
+};
+
+char *egp_reasons[] = {
+       "unspecified",
+       "bad_EGP_header_format",
+       "bad_EGP_data_field_format",
+       "reachability_info_unavailable",
+       "excessive_polling_rate",
+       "no_response",
+       "unsupported_version"
+};
+
+static void
+egpnrprint(register const struct egp_packet *egp, register u_int length)
+{
+       register const u_char *cp;
+       u_int32_t addr;
+       register u_int32_t net;
+       register u_int netlen;
+       int gateways, distances, networks;
+       int t_gateways;
+       char *comma;
+
+       addr = egp->egp_sourcenet;
+       if (IN_CLASSA(addr)) {
+               net = addr & IN_CLASSA_NET;
+               netlen = 1;
+       } else if (IN_CLASSB(addr)) {
+               net = addr & IN_CLASSB_NET;
+               netlen = 2;
+       } else if (IN_CLASSC(addr)) {
+               net = addr & IN_CLASSC_NET;
+               netlen = 3;
+       } else {
+               net = 0;
+               netlen = 0;
+       }
+       cp = (u_char *)(egp + 1);
+
+       t_gateways = egp->egp_intgw + egp->egp_extgw;
+       for (gateways = 0; gateways < t_gateways; ++gateways) {
+               /* Pickup host part of gateway address */
+               addr = 0;
+               TCHECK2(cp[0], 4 - netlen);
+               switch (netlen) {
+
+               case 1:
+                       addr = *cp++;
+                       /* fall through */
+               case 2:
+                       addr = (addr << 8) | *cp++;
+                       /* fall through */
+               case 3:
+                       addr = (addr << 8) | *cp++;
+               }
+               addr |= net;
+               TCHECK2(cp[0], 1);
+               distances = *cp++;
+               printf(" %s %s ",
+                      gateways < (int)egp->egp_intgw ? "int" : "ext",
+                      ipaddr_string(&addr));
+
+               comma = "";
+               putchar('(');
+               while (--distances >= 0) {
+                       TCHECK2(cp[0], 2);
+                       printf("%sd%d:", comma, (int)*cp++);
+                       comma = ", ";
+                       networks = *cp++;
+                       while (--networks >= 0) {
+                               /* Pickup network number */
+                               TCHECK2(cp[0], 1);
+                               addr = (u_int32_t)*cp++ << 24;
+                               if (IN_CLASSB(addr)) {
+                                       TCHECK2(cp[0], 1);
+                                       addr |= (u_int32_t)*cp++ << 16;
+                               } else if (!IN_CLASSA(addr)) {
+                                       TCHECK2(cp[0], 2);
+                                       addr |= (u_int32_t)*cp++ << 16;
+                                       addr |= (u_int32_t)*cp++ << 8;
+                               }
+                               printf(" %s", ipaddr_string(&addr));
+                       }
+               }
+               putchar(')');
+       }
+       return;
+trunc:
+       fputs("[|]", stdout);
+}
+
+void
+egp_print(register const u_char *bp, register u_int length,
+         register const u_char *bp2)
+{
+       register const struct egp_packet *egp;
+       register const struct ip *ip;
+       register int status;
+       register int code;
+       register int type;
+
+       egp = (struct egp_packet *)bp;
+       ip = (struct ip *)bp2;
+        (void)printf("%s > %s: egp: ",
+                    ipaddr_string(&ip->ip_src),
+                    ipaddr_string(&ip->ip_dst));
+
+       if (egp->egp_version != EGP_VERSION) {
+               printf("[version %d]", egp->egp_version);
+               return;
+       }
+       printf("as:%d seq:%d", ntohs(egp->egp_as), ntohs(egp->egp_sequence));
+
+       type = egp->egp_type;
+       code = egp->egp_code;
+       status = egp->egp_status;
+
+       switch (type) {
+       case EGPT_ACQUIRE:
+               printf(" acquire");
+               switch (code) {
+               case EGPC_REQUEST:
+               case EGPC_CONFIRM:
+                       printf(" %s", egp_acquire_codes[code]);
+                       switch (status) {
+                       case EGPS_UNSPEC:
+                       case EGPS_ACTIVE:
+                       case EGPS_PASSIVE:
+                               printf(" %s", egp_acquire_status[status]);
+                               break;
+
+                       default:
+                               printf(" [status %d]", status);
+                               break;
+                       }
+                       printf(" hello:%d poll:%d",
+                              ntohs(egp->egp_hello),
+                              ntohs(egp->egp_poll));
+                       break;
+
+               case EGPC_REFUSE:
+               case EGPC_CEASE:
+               case EGPC_CEASEACK:
+                       printf(" %s", egp_acquire_codes[code]);
+                       switch (status ) {
+                       case EGPS_UNSPEC:
+                       case EGPS_NORES:
+                       case EGPS_ADMIN:
+                       case EGPS_GODOWN:
+                       case EGPS_PARAM:
+                       case EGPS_PROTO:
+                               printf(" %s", egp_acquire_status[status]);
+                               break;
+
+                       default:
+                               printf("[status %d]", status);
+                               break;
+                       }
+                       break;
+
+               default:
+                       printf("[code %d]", code);
+                       break;
+               }
+               break;
+
+       case EGPT_REACH:
+               switch (code) {
+
+               case EGPC_HELLO:
+               case EGPC_HEARDU:
+                       printf(" %s", egp_reach_codes[code]);
+                       if (status <= EGPS_DOWN)
+                               printf(" state:%s", egp_status_updown[status]);
+                       else
+                               printf(" [status %d]", status);
+                       break;
+
+               default:
+                       printf("[reach code %d]", code);
+                       break;
+               }
+               break;
+
+       case EGPT_POLL:
+               printf(" poll");
+               if (egp->egp_status <= EGPS_DOWN)
+                       printf(" state:%s", egp_status_updown[status]);
+               else
+                       printf(" [status %d]", status);
+               printf(" net:%s", ipaddr_string(&egp->egp_sourcenet));
+               break;
+
+       case EGPT_UPDATE:
+               printf(" update");
+               if (status & EGPS_UNSOL) {
+                       status &= ~EGPS_UNSOL;
+                       printf(" unsolicited");
+               }
+               if (status <= EGPS_DOWN)
+                       printf(" state:%s", egp_status_updown[status]);
+               else
+                       printf(" [status %d]", status);
+               printf(" %s int %d ext %d",
+                      ipaddr_string(&egp->egp_sourcenet),
+                      egp->egp_intgw,
+                      egp->egp_extgw);
+               if (vflag)
+                       egpnrprint(egp, length);
+               break;
+
+       case EGPT_ERROR:
+               printf(" error");
+               if (status <= EGPS_DOWN)
+                       printf(" state:%s", egp_status_updown[status]);
+               else
+                       printf(" [status %d]", status);
+
+               if (ntohs(egp->egp_reason) <= EGPR_UVERSION)
+                       printf(" %s", egp_reasons[ntohs(egp->egp_reason)]);
+               else
+                       printf(" [reason %d]", ntohs(egp->egp_reason));
+               break;
+
+       default:
+               printf("[type %d]", type);
+               break;
+       }
+}
diff --git a/tcpdump.tproj/print-ether.c b/tcpdump.tproj/print-ether.c
new file mode 100644 (file)
index 0000000..ae9ddd9
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ether.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <pcap.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ethertype.h"
+
+const u_char *packetp;
+const u_char *snapend;
+
+static inline void
+ether_print(register const u_char *bp, u_int length)
+{
+       register const struct ether_header *ep;
+
+       ep = (const struct ether_header *)bp;
+       if (qflag)
+               (void)printf("%s %s %d: ",
+                            etheraddr_string(ESRC(ep)),
+                            etheraddr_string(EDST(ep)),
+                            length);
+       else
+               (void)printf("%s %s %s %d: ",
+                            etheraddr_string(ESRC(ep)),
+                            etheraddr_string(EDST(ep)),
+                            etherproto_string(ep->ether_type),
+                            length);
+}
+
+/*
+ * This is the top level routine of the printer.  'p' is the points
+ * to the ether header of the packet, 'tvp' is the timestamp,
+ * 'length' is the length of the packet off the wire, and 'caplen'
+ * is the number of bytes actually captured.
+ */
+void
+ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       u_int caplen = h->caplen;
+       u_int length = h->len;
+       struct ether_header *ep;
+       u_short ether_type;
+       extern u_short extracted_ethertype;
+
+       ts_print(&h->ts);
+
+       if (caplen < sizeof(struct ether_header)) {
+               printf("[|ether]");
+               goto out;
+       }
+
+       if (eflag)
+               ether_print(p, length);
+
+       /*
+        * Some printers want to get back at the ethernet addresses,
+        * and/or check that they're not walking off the end of the packet.
+        * Rather than pass them all the way down, we set these globals.
+        */
+       packetp = p;
+       snapend = p + caplen;
+
+       length -= sizeof(struct ether_header);
+       caplen -= sizeof(struct ether_header);
+       ep = (struct ether_header *)p;
+       p += sizeof(struct ether_header);
+
+       ether_type = ntohs(ep->ether_type);
+
+       /*
+        * Is it (gag) an 802.3 encapsulation?
+        */
+       extracted_ethertype = 0;
+       if (ether_type < ETHERMTU) {
+               /* Try to print the LLC-layer header & higher layers */
+               if (llc_print(p, length, caplen, ESRC(ep), EDST(ep)) == 0) {
+                       /* ether_type not known, print raw packet */
+                       if (!eflag)
+                               ether_print((u_char *)ep, length);
+                       if (extracted_ethertype) {
+                               printf("(LLC %s) ",
+                              etherproto_string(htons(extracted_ethertype)));
+                       }
+                       if (!xflag && !qflag)
+                               default_print(p, caplen);
+               }
+       } else if (ether_encap_print(ether_type, p, length, caplen) == 0) {
+               /* ether_type not known, print raw packet */
+               if (!eflag)
+                       ether_print((u_char *)ep, length + sizeof(*ep));
+               if (!xflag && !qflag)
+                       default_print(p, caplen);
+       }
+       if (xflag)
+               default_print(p, caplen);
+ out:
+       putchar('\n');
+}
+
+/*
+ * Prints the packet encapsulated in an Ethernet data segment
+ * (or an equivalent encapsulation), given the Ethernet type code.
+ *
+ * Returns non-zero if it can do so, zero if the ethertype is unknown.
+ *
+ * Stuffs the ether type into a global for the benefit of lower layers
+ * that might want to know what it is.
+ */
+
+u_short        extracted_ethertype;
+
+int
+ether_encap_print(u_short ethertype, const u_char *p,
+    u_int length, u_int caplen)
+{
+       extracted_ethertype = ethertype;
+
+       switch (ethertype) {
+
+       case ETHERTYPE_IP:
+               ip_print(p, length);
+               return (1);
+
+       case ETHERTYPE_ARP:
+       case ETHERTYPE_REVARP:
+               arp_print(p, length, caplen);
+               return (1);
+
+       case ETHERTYPE_DN:
+               decnet_print(p, length, caplen);
+               return (1);
+
+       case ETHERTYPE_ATALK:
+               if (vflag)
+                       fputs("et1 ", stdout);
+               atalk_print(p, length);
+               return (1);
+
+       case ETHERTYPE_AARP:
+               aarp_print(p, length);
+               return (1);
+
+       case ETHERTYPE_LAT:
+       case ETHERTYPE_SCA:
+       case ETHERTYPE_MOPRC:
+       case ETHERTYPE_MOPDL:
+               /* default_print for now */
+       default:
+               return (0);
+       }
+}
diff --git a/tcpdump.tproj/print-fddi.c b/tcpdump.tproj/print-fddi.c
new file mode 100644 (file)
index 0000000..15f8297
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-fddi.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_FDDI
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <pcap.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ethertype.h"
+
+#include "fddi.h"
+
+/*
+ * Some FDDI interfaces use bit-swapped addresses.
+ */
+#if defined(ultrix) || defined(__alpha)
+int    fddi_bitswap = 0;
+#else
+int    fddi_bitswap = 1;
+#endif
+
+/*
+ * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992
+ *
+ * Based in part on code by Van Jacobson, which bears this note:
+ *
+ * NOTE:  This is a very preliminary hack for FDDI support.
+ * There are all sorts of wired in constants & nothing (yet)
+ * to print SMT packets as anything other than hex dumps.
+ * Most of the necessary changes are waiting on my redoing
+ * the "header" that a kernel fddi driver supplies to bpf:  I
+ * want it to look like one byte of 'direction' (0 or 1
+ * depending on whether the packet was inbound or outbound),
+ * two bytes of system/driver dependent data (anything an
+ * implementor thinks would be useful to filter on and/or
+ * save per-packet, then the real 21-byte FDDI header.
+ * Steve McCanne & I have also talked about adding the
+ * 'direction' byte to all bpf headers (e.g., in the two
+ * bytes of padding on an ethernet header).  It's not clear
+ * we could do this in a backwards compatible way & we hate
+ * the idea of an incompatible bpf change.  Discussions are
+ * proceeding.
+ *
+ * Also, to really support FDDI (and better support 802.2
+ * over ethernet) we really need to re-think the rather simple
+ * minded assumptions about fixed length & fixed format link
+ * level headers made in gencode.c.  One day...
+ *
+ *  - vj
+ */
+
+#define FDDI_HDRLEN (sizeof(struct fddi_header))
+
+static u_char fddi_bit_swap[] = {
+       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+       0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+       0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+       0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+       0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+       0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+       0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+       0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+       0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+       0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+       0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+       0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+       0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+       0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+       0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+       0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+       0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+/*
+ * Print FDDI frame-control bits
+ */
+static inline void
+print_fddi_fc(u_char fc)
+{
+       switch (fc) {
+
+       case FDDIFC_VOID:                         /* Void frame */
+               printf("void ");
+               break;
+
+       case FDDIFC_NRT:                          /* Nonrestricted token */
+               printf("nrt ");
+               break;
+
+       case FDDIFC_RT:                           /* Restricted token */
+               printf("rt ");
+               break;
+
+       case FDDIFC_SMT_INFO:                     /* SMT Info */
+               printf("info ");
+               break;
+
+       case FDDIFC_SMT_NSA:                      /* SMT Next station adrs */
+               printf("nsa ");
+               break;
+
+       case FDDIFC_MAC_BEACON:                   /* MAC Beacon frame */
+               printf("beacon ");
+               break;
+
+       case FDDIFC_MAC_CLAIM:                    /* MAC Claim frame */
+               printf("claim ");
+               break;
+
+       default:
+               switch (fc & FDDIFC_CLFF) {
+
+               case FDDIFC_MAC:
+                       printf("mac%1x ", fc & FDDIFC_ZZZZ);
+                       break;
+
+               case FDDIFC_SMT:
+                       printf("smt%1x ", fc & FDDIFC_ZZZZ);
+                       break;
+
+               case FDDIFC_LLC_ASYNC:
+                       printf("async%1x ", fc & FDDIFC_ZZZZ);
+                       break;
+
+               case FDDIFC_LLC_SYNC:
+                       printf("sync%1x ", fc & FDDIFC_ZZZZ);
+                       break;
+
+               case FDDIFC_IMP_ASYNC:
+                       printf("imp_async%1x ", fc & FDDIFC_ZZZZ);
+                       break;
+
+               case FDDIFC_IMP_SYNC:
+                       printf("imp_sync%1x ", fc & FDDIFC_ZZZZ);
+                       break;
+
+               default:
+                       printf("%02x ", fc);
+                       break;
+               }
+       }
+}
+
+/* Extract src, dst addresses */
+static inline void
+extract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst)
+{
+       register int i;
+
+       if (fddi_bitswap) {
+               /*
+                * bit-swap the fddi addresses (isn't the IEEE standards
+                * process wonderful!) then convert them to names.
+                */
+               for (i = 0; i < 6; ++i)
+                       fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]];
+               for (i = 0; i < 6; ++i)
+                       fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]];
+       }
+       else {
+               memcpy(fdst, (char *)fddip->fddi_dhost, 6);
+               memcpy(fsrc, (char *)fddip->fddi_shost, 6);
+       }
+}
+
+/*
+ * Print the FDDI MAC header
+ */
+static inline void
+fddi_print(register const struct fddi_header *fddip, register u_int length,
+          register const u_char *fsrc, register const u_char *fdst)
+{
+       char *srcname, *dstname;
+
+       srcname = etheraddr_string(fsrc);
+       dstname = etheraddr_string(fdst);
+
+       if (vflag)
+               (void) printf("%02x %s %s %d: ",
+                      fddip->fddi_fc,
+                      srcname, dstname,
+                      length);
+       else if (qflag)
+               printf("%s %s %d: ", srcname, dstname, length);
+       else {
+               (void) print_fddi_fc(fddip->fddi_fc);
+               (void) printf("%s %s %d: ", srcname, dstname, length);
+       }
+}
+
+static inline void
+fddi_smt_print(const u_char *p, u_int length)
+{
+       printf("<SMT printer not yet implemented>");
+}
+
+/*
+ * This is the top level routine of the printer.  'sp' is the points
+ * to the FDDI header of the packet, 'tvp' is the timestamp,
+ * 'length' is the length of the packet off the wire, and 'caplen'
+ * is the number of bytes actually captured.
+ */
+void
+fddi_if_print(u_char *pcap, const struct pcap_pkthdr *h,
+             register const u_char *p)
+{
+       u_int caplen = h->caplen;
+       u_int length = h->len;
+       const struct fddi_header *fddip = (struct fddi_header *)p;
+       extern u_short extracted_ethertype;
+       struct ether_header ehdr;
+
+       ts_print(&h->ts);
+
+       if (caplen < FDDI_HDRLEN) {
+               printf("[|fddi]");
+               goto out;
+       }
+       /*
+        * Get the FDDI addresses into a canonical form
+        */
+       extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr));
+       /*
+        * Some printers want to get back at the link level addresses,
+        * and/or check that they're not walking off the end of the packet.
+        * Rather than pass them all the way down, we set these globals.
+        */
+       snapend = p + caplen;
+       /*
+        * Actually, the only printer that uses packetp is print-bootp.c,
+        * and it assumes that packetp points to an Ethernet header.  The
+        * right thing to do is to fix print-bootp.c to know which link
+        * type is in use when it excavates. XXX
+        */
+       packetp = (u_char *)&ehdr;
+
+       if (eflag)
+               fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
+
+       /* Skip over FDDI MAC header */
+       length -= FDDI_HDRLEN;
+       p += FDDI_HDRLEN;
+       caplen -= FDDI_HDRLEN;
+
+       /* Frame Control field determines interpretation of packet */
+       extracted_ethertype = 0;
+       if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) {
+               /* Try to print the LLC-layer header & higher layers */
+               if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr))
+                   == 0) {
+                       /*
+                        * Some kinds of LLC packet we cannot
+                        * handle intelligently
+                        */
+                       if (!eflag)
+                               fddi_print(fddip, length,
+                                   ESRC(&ehdr), EDST(&ehdr));
+                       if (extracted_ethertype) {
+                               printf("(LLC %s) ",
+                       etherproto_string(htons(extracted_ethertype)));
+                       }
+                       if (!xflag && !qflag)
+                               default_print(p, caplen);
+               }
+       } else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT)
+               fddi_smt_print(p, caplen);
+       else {
+               /* Some kinds of FDDI packet we cannot handle intelligently */
+               if (!eflag)
+                       fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr));
+               if (!xflag && !qflag)
+                       default_print(p, caplen);
+       }
+       if (xflag)
+               default_print(p, caplen);
+out:
+       putchar('\n');
+}
+#else
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+
+#include "interface.h"
+void
+fddi_if_print(u_char *pcap, const struct pcap_pkthdr *h,
+             register const u_char *p)
+{
+
+       error("not configured for fddi");
+       /* NOTREACHED */
+}
+#endif
diff --git a/tcpdump.tproj/print-gre.c b/tcpdump.tproj/print-gre.c
new file mode 100644 (file)
index 0000000..94e42db
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1996
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Lawrence Berkeley Laboratory,
+ * Berkeley, CA.  The name of the University may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Initial contribution from John Hawkinson <jhawk@bbnplanet.com>
+ *
+ * This module implements support for decoding GRE (Generic Routing
+ * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702.
+ * This code only supports the IP encapsulation thereof.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-gre.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netdb.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"           /* must come after interface.h */
+
+#define GRE_SIZE (20)
+
+struct gre {
+       u_short flags;
+       u_short proto;
+       union {
+               struct gre_ckof {
+                       u_short cksum;
+                       u_short offset;
+               }        gre_ckof;
+               u_int32_t key;
+               u_int32_t seq;
+       }     gre_void1;
+       union {
+               u_int32_t key;
+               u_int32_t seq;
+               u_int32_t routing;
+       }     gre_void2;
+       union {
+               u_int32_t seq;
+               u_int32_t routing;
+       }     gre_void3;
+       union {
+               u_int32_t routing;
+       }     gre_void4;
+};
+
+#define GRE_CP         0x8000  /* Checksum Present */
+#define GRE_RP         0x4000  /* Routing Present */
+#define GRE_KP         0x2000  /* Key Present */
+#define GRE_SP         0x1000  /* Sequence Present */
+
+
+#define GREPROTO_IP    0x0800
+
+
+/*
+ * Deencapsulate and print a GRE-tunneled IP datagram
+ */
+void
+gre_print(const u_char *bp, u_int length)
+{
+       const u_char *cp = bp + 4;
+       const struct gre *gre;
+       u_short flags, proto;
+
+       gre = (const struct gre *)bp;
+
+       if (length < GRE_SIZE) {
+               goto trunc;
+       }
+       flags = EXTRACT_16BITS(&gre->flags);
+       proto = EXTRACT_16BITS(&gre->proto);
+
+       if (vflag) {
+               /* Decode the flags */
+               putchar('[');
+               if (flags & GRE_CP)
+                       putchar('C');
+               if (flags & GRE_RP)
+                       putchar('R');
+               if (flags & GRE_KP)
+                       putchar('K');
+               if (flags & GRE_SP)
+                       putchar('S');
+               fputs("] ", stdout);
+       }
+       /* Checksum & Offset are present */
+       if ((flags & GRE_CP) | (flags & GRE_RP))
+               cp += 4;
+
+       /* We don't support routing fields (variable length) now. Punt. */
+       if (flags & GRE_RP)
+               return;
+
+       if (flags & GRE_KP)
+               cp += 4;
+       if (flags & GRE_SP)
+               cp += 4;
+
+       switch (proto) {
+
+       case GREPROTO_IP:
+               ip_print(cp, length - ((cp - bp) / sizeof(u_char)));
+               break;
+
+       default:
+               printf("gre-proto-0x%04X", proto);
+               break;
+       }
+       return;
+
+trunc:
+       fputs("[|gre]", stdout);
+
+}
diff --git a/tcpdump.tproj/print-icmp.c b/tcpdump.tproj/print-icmp.c
new file mode 100644 (file)
index 0000000..d4eb3fa
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-icmp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"                   /* must come after interface.h */
+
+/* rfc1700 */
+#ifndef ICMP_UNREACH_NET_UNKNOWN
+#define ICMP_UNREACH_NET_UNKNOWN       6       /* destination net unknown */
+#endif
+#ifndef ICMP_UNREACH_HOST_UNKNOWN
+#define ICMP_UNREACH_HOST_UNKNOWN      7       /* destination host unknown */
+#endif
+#ifndef ICMP_UNREACH_ISOLATED
+#define ICMP_UNREACH_ISOLATED          8       /* source host isolated */
+#endif
+#ifndef ICMP_UNREACH_NET_PROHIB
+#define ICMP_UNREACH_NET_PROHIB                9       /* admin prohibited net */
+#endif
+#ifndef ICMP_UNREACH_HOST_PROHIB
+#define ICMP_UNREACH_HOST_PROHIB       10      /* admin prohibited host */
+#endif
+#ifndef ICMP_UNREACH_TOSNET
+#define ICMP_UNREACH_TOSNET            11      /* tos prohibited net */
+#endif
+#ifndef ICMP_UNREACH_TOSHOST
+#define ICMP_UNREACH_TOSHOST           12      /* tos prohibited host */
+#endif
+
+/* rfc1716 */
+#ifndef ICMP_UNREACH_FILTER_PROHIB
+#define ICMP_UNREACH_FILTER_PROHIB     13      /* admin prohibited filter */
+#endif
+#ifndef ICMP_UNREACH_HOST_PRECEDENCE
+#define ICMP_UNREACH_HOST_PRECEDENCE   14      /* host precedence violation */
+#endif
+#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
+#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15      /* precedence cutoff */
+#endif
+
+/* rfc1256 */
+#ifndef ICMP_ROUTERADVERT
+#define ICMP_ROUTERADVERT              9       /* router advertisement */
+#endif
+#ifndef ICMP_ROUTERSOLICIT
+#define ICMP_ROUTERSOLICIT             10      /* router solicitation */
+#endif
+
+/* Most of the icmp types */
+static struct tok icmp2str[] = {
+       { ICMP_ECHOREPLY,               "echo reply" },
+       { ICMP_SOURCEQUENCH,            "source quench" },
+       { ICMP_ECHO,                    "echo request" },
+       { ICMP_ROUTERSOLICIT,           "router solicitation" },
+       { ICMP_TSTAMP,                  "time stamp request" },
+       { ICMP_TSTAMPREPLY,             "time stamp reply" },
+       { ICMP_IREQ,                    "information request" },
+       { ICMP_IREQREPLY,               "information reply" },
+       { ICMP_MASKREQ,                 "address mask request" },
+       { 0,                            NULL }
+};
+
+/* Formats for most of the ICMP_UNREACH codes */
+static struct tok unreach2str[] = {
+       { ICMP_UNREACH_NET,             "net %s unreachable" },
+       { ICMP_UNREACH_HOST,            "host %s unreachable" },
+       { ICMP_UNREACH_SRCFAIL,
+           "%s unreachable - source route failed" },
+       { ICMP_UNREACH_NET_UNKNOWN,     "net %s unreachable - unknown" },
+       { ICMP_UNREACH_HOST_UNKNOWN,    "host %s unreachable - unknown" },
+       { ICMP_UNREACH_ISOLATED,
+           "%s unreachable - source host isolated" },
+       { ICMP_UNREACH_NET_PROHIB,
+           "net %s unreachable - admin prohibited" },
+       { ICMP_UNREACH_HOST_PROHIB,
+           "host %s unreachable - admin prohibited" },
+       { ICMP_UNREACH_TOSNET,
+           "net %s unreachable - tos prohibited" },
+       { ICMP_UNREACH_TOSHOST,
+           "host %s unreachable - tos prohibited" },
+       { ICMP_UNREACH_FILTER_PROHIB,
+           "host %s unreachable - admin prohibited filter" },
+       { ICMP_UNREACH_HOST_PRECEDENCE,
+           "host %s unreachable - host precedence violation" },
+       { ICMP_UNREACH_PRECEDENCE_CUTOFF,
+           "host %s unreachable - precedence cutoff" },
+       { 0,                            NULL }
+};
+
+/* Formats for the ICMP_REDIRECT codes */
+static struct tok type2str[] = {
+       { ICMP_REDIRECT_NET,            "redirect %s to net %s" },
+       { ICMP_REDIRECT_HOST,           "redirect %s to host %s" },
+       { ICMP_REDIRECT_TOSNET,         "redirect-tos %s to net %s" },
+       { ICMP_REDIRECT_TOSHOST,        "redirect-tos %s to net %s" },
+       { 0,                            NULL }
+};
+
+/* rfc1191 */
+struct mtu_discovery {
+       short unused;
+       short nexthopmtu;
+};
+
+/* rfc1256 */
+struct ih_rdiscovery {
+       u_char ird_addrnum;
+       u_char ird_addrsiz;
+       u_short ird_lifetime;
+};
+
+struct id_rdiscovery {
+       u_int32_t ird_addr;
+       u_int32_t ird_pref;
+};
+
+void
+icmp_print(register const u_char *bp, register const u_char *bp2)
+{
+       register char *cp;
+       register const struct icmp *dp;
+       register const struct ip *ip;
+       register const char *str, *fmt;
+       register const struct ip *oip;
+       register const struct udphdr *ouh;
+       register u_int hlen, dport, mtu;
+       char buf[256];
+
+       dp = (struct icmp *)bp;
+       ip = (struct ip *)bp2;
+       str = buf;
+
+        (void)printf("%s > %s: ",
+               ipaddr_string(&ip->ip_src),
+               ipaddr_string(&ip->ip_dst));
+
+       TCHECK(dp->icmp_code);
+       switch (dp->icmp_type) {
+
+       case ICMP_UNREACH:
+               TCHECK(dp->icmp_ip.ip_dst);
+               switch (dp->icmp_code) {
+
+               case ICMP_UNREACH_PROTOCOL:
+                       TCHECK(dp->icmp_ip.ip_p);
+                       (void)sprintf(buf, "%s protocol %d unreachable",
+                                      ipaddr_string(&dp->icmp_ip.ip_dst),
+                                      dp->icmp_ip.ip_p);
+                       break;
+
+               case ICMP_UNREACH_PORT:
+                       TCHECK(dp->icmp_ip.ip_p);
+                       oip = &dp->icmp_ip;
+                       hlen = oip->ip_hl * 4;
+                       ouh = (struct udphdr *)(((u_char *)oip) + hlen);
+                       dport = ntohs(ouh->uh_dport);
+                       switch (oip->ip_p) {
+
+                       case IPPROTO_TCP:
+                               (void)sprintf(buf,
+                                       "%s tcp port %s unreachable",
+                                       ipaddr_string(&oip->ip_dst),
+                                       tcpport_string(dport));
+                               break;
+
+                       case IPPROTO_UDP:
+                               (void)sprintf(buf,
+                                       "%s udp port %s unreachable",
+                                       ipaddr_string(&oip->ip_dst),
+                                       udpport_string(dport));
+                               break;
+
+                       default:
+                               (void)sprintf(buf,
+                                       "%s protocol %d port %d unreachable",
+                                       ipaddr_string(&oip->ip_dst),
+                                       oip->ip_p, dport);
+                               break;
+                       }
+                       break;
+
+               case ICMP_UNREACH_NEEDFRAG:
+                       {
+                       register const struct mtu_discovery *mp;
+
+                       mp = (struct mtu_discovery *)&dp->icmp_void;
+                        mtu = EXTRACT_16BITS(&mp->nexthopmtu);
+                        if (mtu)
+                           (void)sprintf(buf,
+                               "%s unreachable - need to frag (mtu %d)",
+                               ipaddr_string(&dp->icmp_ip.ip_dst), mtu);
+                        else
+                           (void)sprintf(buf,
+                               "%s unreachable - need to frag",
+                               ipaddr_string(&dp->icmp_ip.ip_dst));
+                       }
+                       break;
+
+               default:
+                       fmt = tok2str(unreach2str, "#%d %%s unreachable",
+                           dp->icmp_code);
+                       (void)sprintf(buf, fmt,
+                           ipaddr_string(&dp->icmp_ip.ip_dst));
+                       break;
+               }
+               break;
+
+       case ICMP_REDIRECT:
+               TCHECK(dp->icmp_ip.ip_dst);
+               fmt = tok2str(type2str, "redirect-#%d %%s to net %%s",
+                   dp->icmp_code);
+               (void)sprintf(buf, fmt,
+                   ipaddr_string(&dp->icmp_ip.ip_dst),
+                   ipaddr_string(&dp->icmp_gwaddr));
+               break;
+
+       case ICMP_ROUTERADVERT:
+               {
+               register const struct ih_rdiscovery *ihp;
+               register const struct id_rdiscovery *idp;
+               u_int lifetime, num, size;
+
+               (void)strcpy(buf, "router advertisement");
+               cp = buf + strlen(buf);
+
+               ihp = (struct ih_rdiscovery *)&dp->icmp_void;
+               TCHECK(*ihp);
+               (void)strcpy(cp, " lifetime ");
+               cp = buf + strlen(buf);
+               lifetime = EXTRACT_16BITS(&ihp->ird_lifetime);
+               if (lifetime < 60)
+                       (void)sprintf(cp, "%u", lifetime);
+               else if (lifetime < 60 * 60)
+                       (void)sprintf(cp, "%u:%02u",
+                           lifetime / 60, lifetime % 60);
+               else
+                       (void)sprintf(cp, "%u:%02u:%02u",
+                           lifetime / 3600,
+                           (lifetime % 3600) / 60,
+                           lifetime % 60);
+               cp = buf + strlen(buf);
+
+               num = ihp->ird_addrnum;
+               (void)sprintf(cp, " %d:", num);
+               cp = buf + strlen(buf);
+
+               size = ihp->ird_addrsiz;
+               if (size != 2) {
+                       (void)sprintf(cp, " [size %d]", size);
+                       break;
+               }
+               idp = (struct id_rdiscovery *)&dp->icmp_data;
+               while (num-- > 0) {
+                       TCHECK(*idp);
+                       (void)sprintf(cp, " {%s %u}",
+                           ipaddr_string(&idp->ird_addr),
+                           EXTRACT_32BITS(&idp->ird_pref));
+                       cp = buf + strlen(buf);
+               }
+               }
+               break;
+
+       case ICMP_TIMXCEED:
+               TCHECK(dp->icmp_ip.ip_dst);
+               switch (dp->icmp_code) {
+
+               case ICMP_TIMXCEED_INTRANS:
+                       str = "time exceeded in-transit";
+                       break;
+
+               case ICMP_TIMXCEED_REASS:
+                       str = "ip reassembly time exceeded";
+                       break;
+
+               default:
+                       (void)sprintf(buf, "time exceeded-#%d", dp->icmp_code);
+                       break;
+               }
+               break;
+
+       case ICMP_PARAMPROB:
+               if (dp->icmp_code)
+                       (void)sprintf(buf, "parameter problem - code %d",
+                                       dp->icmp_code);
+               else {
+                       TCHECK(dp->icmp_pptr);
+                       (void)sprintf(buf, "parameter problem - octet %d",
+                                       dp->icmp_pptr);
+               }
+               break;
+
+       case ICMP_MASKREPLY:
+               TCHECK(dp->icmp_mask);
+               (void)sprintf(buf, "address mask is 0x%08x",
+                   (u_int32_t)ntohl(dp->icmp_mask));
+               break;
+
+       default:
+               str = tok2str(icmp2str, "type-#%d", dp->icmp_type);
+               break;
+       }
+        (void)printf("icmp: %s", str);
+       return;
+trunc:
+       fputs("[|icmp]", stdout);
+}
diff --git a/tcpdump.tproj/print-igrp.c b/tcpdump.tproj/print-igrp.c
new file mode 100644 (file)
index 0000000..a35e6ac
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Initial contribution from Francis Dupont (francis.dupont@inria.fr)
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-igrp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "addrtoname.h"
+#include "interface.h"
+#include "igrp.h"
+#include "extract.h"                   /* must come after interface.h */
+
+static void
+igrp_entry_print(register struct igrprte *igr, register int is_interior,
+    register int is_exterior)
+{
+       register u_int delay, bandwidth;
+       u_int metric, mtu;
+
+       if (is_interior)
+               printf(" *.%d.%d.%d", igr->igr_net[0],
+                   igr->igr_net[1], igr->igr_net[2]);
+       else if (is_exterior)
+               printf(" X%d.%d.%d.0", igr->igr_net[0],
+                   igr->igr_net[1], igr->igr_net[2]);
+       else
+               printf(" %d.%d.%d.0", igr->igr_net[0],
+                   igr->igr_net[1], igr->igr_net[2]);
+
+       delay = EXTRACT_24BITS(igr->igr_dly);
+       bandwidth = EXTRACT_24BITS(igr->igr_bw);
+       metric = bandwidth + delay;
+       if (metric > 0xffffff)
+               metric = 0xffffff;
+       mtu = EXTRACT_16BITS(igr->igr_mtu);
+
+       printf(" d=%d b=%d r=%d l=%d M=%d mtu=%d in %d hops",
+           10 * delay, bandwidth == 0 ? 0 : 10000000 / bandwidth,
+           igr->igr_rel, igr->igr_ld, metric,
+           mtu, igr->igr_hct);
+}
+
+static struct tok op2str[] = {
+       { IGRP_UPDATE,          "update" },
+       { IGRP_REQUEST,         "request" },
+       { 0,                    NULL }
+};
+
+void
+igrp_print(register const u_char *bp, u_int length, register const u_char *bp2)
+{
+       register struct igrphdr *hdr;
+       register struct ip *ip;
+       register u_char *cp;
+       u_int nint, nsys, next;
+
+       hdr = (struct igrphdr *)bp;
+       ip = (struct ip *)bp2;
+       cp = (u_char *)(hdr + 1);
+        (void)printf("%s > %s: igrp: ",
+           ipaddr_string(&ip->ip_src),
+           ipaddr_string(&ip->ip_dst));
+
+       /* Header */
+       TCHECK(*hdr);
+       nint = EXTRACT_16BITS(&hdr->ig_ni);
+       nsys = EXTRACT_16BITS(&hdr->ig_ns);
+       next = EXTRACT_16BITS(&hdr->ig_nx);
+
+       (void)printf(" %s V%d edit=%d AS=%d (%d/%d/%d)",
+           tok2str(op2str, "op-#%d", hdr->ig_op),
+           hdr->ig_v,
+           hdr->ig_ed,
+           EXTRACT_16BITS(&hdr->ig_as),
+           nint,
+           nsys,
+           next);
+
+       length -= sizeof(*hdr);
+       while (length >= IGRP_RTE_SIZE) {
+               if (nint > 0) {
+                       TCHECK2(*cp, IGRP_RTE_SIZE);
+                       igrp_entry_print((struct igrprte *)cp, 1, 0);
+                       --nint;
+               } else if (nsys > 0) {
+                       TCHECK2(*cp, IGRP_RTE_SIZE);
+                       igrp_entry_print((struct igrprte *)cp, 0, 0);
+                       --nsys;
+               } else if (next > 0) {
+                       TCHECK2(*cp, IGRP_RTE_SIZE);
+                       igrp_entry_print((struct igrprte *)cp, 0, 1);
+                       --next;
+               } else {
+                       (void)printf("[extra bytes %d]", length);
+                       break;
+               }
+               cp += IGRP_RTE_SIZE;
+               length -= IGRP_RTE_SIZE;
+       }
+       if (nint == 0 && nsys == 0 && next == 0)
+               return;
+trunc:
+       fputs("[|igrp]", stdout);
+}
diff --git a/tcpdump.tproj/print-ip.c b/tcpdump.tproj/print-ip.c
new file mode 100644 (file)
index 0000000..6c0c31c
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ip.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "addrtoname.h"
+#include "interface.h"
+#include "extract.h"                   /* must come after interface.h */
+
+/* Compatibility */
+#ifndef        IPPROTO_ND
+#define        IPPROTO_ND      77
+#endif
+
+#ifndef IN_CLASSD
+#define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
+#endif
+
+/* (following from ipmulti/mrouted/prune.h) */
+
+/*
+ * The packet format for a traceroute request.
+ */
+struct tr_query {
+       u_int  tr_src;                  /* traceroute source */
+       u_int  tr_dst;                  /* traceroute destination */
+       u_int  tr_raddr;                /* traceroute response address */
+#ifdef WORDS_BIGENDIAN
+       struct {
+               u_int   ttl : 8;        /* traceroute response ttl */
+               u_int   qid : 24;       /* traceroute query id */
+       } q;
+#else
+       struct {
+               u_int   qid : 24;       /* traceroute query id */
+               u_int   ttl : 8;        /* traceroute response ttl */
+       } q;
+#endif
+};
+
+#define tr_rttl q.ttl
+#define tr_qid  q.qid
+
+/*
+ * Traceroute response format.  A traceroute response has a tr_query at the
+ * beginning, followed by one tr_resp for each hop taken.
+ */
+struct tr_resp {
+       u_int tr_qarr;                  /* query arrival time */
+       u_int tr_inaddr;                /* incoming interface address */
+       u_int tr_outaddr;               /* outgoing interface address */
+       u_int tr_rmtaddr;               /* parent address in source tree */
+       u_int tr_vifin;                 /* input packet count on interface */
+       u_int tr_vifout;                /* output packet count on interface */
+       u_int tr_pktcnt;                /* total incoming packets for src-grp */
+       u_char  tr_rproto;              /* routing proto deployed on router */
+       u_char  tr_fttl;                /* ttl required to forward on outvif */
+       u_char  tr_smask;               /* subnet mask for src addr */
+       u_char  tr_rflags;              /* forwarding error codes */
+};
+
+/* defs within mtrace */
+#define TR_QUERY 1
+#define TR_RESP        2
+
+/* fields for tr_rflags (forwarding error codes) */
+#define TR_NO_ERR      0
+#define TR_WRONG_IF    1
+#define TR_PRUNED      2
+#define TR_OPRUNED     3
+#define TR_SCOPED      4
+#define TR_NO_RTE      5
+#define TR_NO_FWD      7
+#define TR_NO_SPACE    0x81
+#define TR_OLD_ROUTER  0x82
+
+/* fields for tr_rproto (routing protocol) */
+#define TR_PROTO_DVMRP 1
+#define TR_PROTO_MOSPF 2
+#define TR_PROTO_PIM   3
+#define TR_PROTO_CBT   4
+
+static void print_mtrace(register const u_char *bp, register u_int len)
+{
+       register struct tr_query *tr = (struct tr_query *)(bp + 8);
+
+       printf("mtrace %d: %s to %s reply-to %s", tr->tr_qid,
+               ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
+               ipaddr_string(&tr->tr_raddr));
+       if (IN_CLASSD(ntohl(tr->tr_raddr)))
+               printf(" with-ttl %d", tr->tr_rttl);
+}
+
+static void print_mresp(register const u_char *bp, register u_int len)
+{
+       register struct tr_query *tr = (struct tr_query *)(bp + 8);
+
+       printf("mresp %d: %s to %s reply-to %s", tr->tr_qid,
+               ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
+               ipaddr_string(&tr->tr_raddr));
+       if (IN_CLASSD(ntohl(tr->tr_raddr)))
+               printf(" with-ttl %d", tr->tr_rttl);
+}
+
+static void
+igmp_print(register const u_char *bp, register u_int len,
+          register const u_char *bp2)
+{
+       register const struct ip *ip;
+
+       ip = (const struct ip *)bp2;
+        (void)printf("%s > %s: ",
+               ipaddr_string(&ip->ip_src),
+               ipaddr_string(&ip->ip_dst));
+
+       TCHECK2(bp[0], 8);
+       switch (bp[0]) {
+       case 0x11:
+               (void)printf("igmp query");
+               if (*(int *)&bp[4])
+                       (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
+               if (len != 8)
+                       (void)printf(" [len %d]", len);
+               break;
+       case 0x12:
+               (void)printf("igmp report %s", ipaddr_string(&bp[4]));
+               if (len != 8)
+                       (void)printf(" [len %d]", len);
+               break;
+       case 0x16:
+               (void)printf("igmp nreport %s", ipaddr_string(&bp[4]));
+               break;
+       case 0x17:
+               (void)printf("igmp leave %s", ipaddr_string(&bp[4]));
+               break;
+       case 0x13:
+               (void)printf("igmp dvmrp");
+               if (len < 8)
+                       (void)printf(" [len %d]", len);
+               else
+                       dvmrp_print(bp, len);
+               break;
+       case 0x14:
+               (void)printf("igmp pim");
+               pim_print(bp, len);
+               break;
+       case 0x1e:
+               print_mresp(bp, len);
+               break;
+       case 0x1f:
+               print_mtrace(bp, len);
+               break;
+       default:
+               (void)printf("igmp-%d", bp[0] & 0xf);
+               break;
+       }
+       if ((bp[0] >> 4) != 1)
+               (void)printf(" [v%d]", bp[0] >> 4);
+
+       TCHECK2(bp[0], len);
+       if (vflag) {
+               /* Check the IGMP checksum */
+               u_int32_t sum = 0;
+               int count;
+               const u_short *sp = (u_short *)bp;
+               
+               for (count = len / 2; --count >= 0; )
+                       sum += *sp++;
+               if (len & 1)
+                       sum += ntohs(*(u_char *) sp << 8);
+               while (sum >> 16)
+                       sum = (sum & 0xffff) + (sum >> 16);
+               sum = 0xffff & ~sum;
+               if (sum != 0)
+                       printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
+       }
+       return;
+trunc:
+       fputs("[|igmp]", stdout);
+}
+
+/*
+ * print the recorded route in an IP RR, LSRR or SSRR option.
+ */
+static void
+ip_printroute(const char *type, register const u_char *cp, u_int length)
+{
+       register u_int ptr = cp[2] - 1;
+       register u_int len;
+
+       printf(" %s{", type);
+       if ((length + 1) & 3)
+               printf(" [bad length %d]", length);
+       if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
+               printf(" [bad ptr %d]", cp[2]);
+
+       type = "";
+       for (len = 3; len < length; len += 4) {
+               if (ptr == len)
+                       type = "#";
+               printf("%s%s", type, ipaddr_string(&cp[len]));
+               type = " ";
+       }
+       printf("%s}", ptr == len? "#" : "");
+}
+
+/*
+ * print IP options.
+ */
+static void
+ip_optprint(register const u_char *cp, u_int length)
+{
+       register u_int len;
+
+       for (; length > 0; cp += len, length -= len) {
+               int tt = *cp;
+
+               len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
+               if (len <= 0) {
+                       printf("[|ip op len %d]", len);
+                       return;
+               }
+               if (&cp[1] >= snapend || cp + len > snapend) {
+                       printf("[|ip]");
+                       return;
+               }
+               switch (tt) {
+
+               case IPOPT_EOL:
+                       printf(" EOL");
+                       if (length > 1)
+                               printf("-%d", length - 1);
+                       return;
+
+               case IPOPT_NOP:
+                       printf(" NOP");
+                       break;
+
+               case IPOPT_TS:
+                       printf(" TS{%d}", len);
+                       break;
+
+               case IPOPT_SECURITY:
+                       printf(" SECURITY{%d}", len);
+                       break;
+
+               case IPOPT_RR:
+                       printf(" RR{%d}=", len);
+                       ip_printroute("RR", cp, len);
+                       break;
+
+               case IPOPT_SSRR:
+                       ip_printroute("SSRR", cp, len);
+                       break;
+
+               case IPOPT_LSRR:
+                       ip_printroute("LSRR", cp, len);
+                       break;
+
+               default:
+                       printf(" IPOPT-%d{%d}", cp[0], len);
+                       break;
+               }
+       }
+}
+
+/*
+ * compute an IP header checksum.
+ * don't modifiy the packet.
+ */
+static int
+in_cksum(const struct ip *ip)
+{
+       register const u_short *sp = (u_short *)ip;
+       register u_int32_t sum = 0;
+       register int count;
+
+       /*
+        * No need for endian conversions.
+        */
+       for (count = ip->ip_hl * 2; --count >= 0; )
+               sum += *sp++;
+       while (sum > 0xffff)
+               sum = (sum & 0xffff) + (sum >> 16);
+       sum = ~sum & 0xffff;
+
+       return (sum);
+}
+
+/*
+ * print an IP datagram.
+ */
+void
+ip_print(register const u_char *bp, register u_int length)
+{
+       register const struct ip *ip;
+       register u_int hlen, len, off;
+       register const u_char *cp;
+
+       ip = (const struct ip *)bp;
+#ifdef LBL_ALIGN
+       /*
+        * If the IP header is not aligned, copy into abuf.
+        * This will never happen with BPF.  It does happen raw packet
+        * dumps from -r.
+        */
+       if ((long)ip & 3) {
+               static u_char *abuf = NULL;
+               static int didwarn = 0;
+
+               if (abuf == NULL) {
+                       abuf = (u_char *)malloc(snaplen);
+                       if (abuf == NULL)
+                               error("ip_print: malloc");
+               }
+               memcpy((char *)abuf, (char *)ip, min(length, snaplen));
+               snapend += abuf - (u_char *)ip;
+               packetp = abuf;
+               ip = (struct ip *)abuf;
+               /* We really want libpcap to give us aligned packets */
+               if (!didwarn) {
+                       warning("compensating for unaligned libpcap packets");
+                       ++didwarn;
+               }
+       }
+#endif
+       if ((u_char *)(ip + 1) > snapend) {
+               printf("[|ip]");
+               return;
+       }
+       if (length < sizeof (struct ip)) {
+               (void)printf("truncated-ip %d", length);
+               return;
+       }
+       hlen = ip->ip_hl * 4;
+
+       len = ntohs(ip->ip_len);
+       if (length < len)
+               (void)printf("truncated-ip - %d bytes missing!",
+                       len - length);
+       len -= hlen;
+
+       /*
+        * If this is fragment zero, hand it to the next higher
+        * level protocol.
+        */
+       off = ntohs(ip->ip_off);
+       if ((off & 0x1fff) == 0) {
+               cp = (const u_char *)ip + hlen;
+               switch (ip->ip_p) {
+
+               case IPPROTO_TCP:
+                       tcp_print(cp, len, (const u_char *)ip);
+                       break;
+
+               case IPPROTO_UDP:
+                       udp_print(cp, len, (const u_char *)ip);
+                       break;
+
+               case IPPROTO_ICMP:
+                       icmp_print(cp, (const u_char *)ip);
+                       break;
+
+#ifndef IPPROTO_IGRP
+#define IPPROTO_IGRP 9
+#endif
+               case IPPROTO_IGRP:
+                       igrp_print(cp, len, (const u_char *)ip);
+                       break;
+
+               case IPPROTO_ND:
+                       (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
+                               ipaddr_string(&ip->ip_dst));
+                       (void)printf(" nd %d", len);
+                       break;
+
+               case IPPROTO_EGP:
+                       egp_print(cp, len, (const u_char *)ip);
+                       break;
+
+#ifndef IPPROTO_OSPF
+#define IPPROTO_OSPF 89
+#endif
+               case IPPROTO_OSPF:
+                       ospf_print(cp, len, (const u_char *)ip);
+                       break;
+
+#ifndef IPPROTO_IGMP
+#define IPPROTO_IGMP 2
+#endif
+               case IPPROTO_IGMP:
+                       igmp_print(cp, len, (const u_char *)ip);
+                       break;
+
+#ifndef IPPROTO_ENCAP
+#define IPPROTO_ENCAP 4
+#endif
+               case IPPROTO_ENCAP:
+                       /* ip-in-ip encapsulation */
+                       if (vflag)
+                               (void)printf("%s > %s: ",
+                                            ipaddr_string(&ip->ip_src),
+                                            ipaddr_string(&ip->ip_dst));
+                       ip_print(cp, len);
+                       if (! vflag) {
+                               printf(" (encap)");
+                               return;
+                       }
+                       break;
+
+#ifndef IPPROTO_GRE
+#define IPPROTO_GRE 47
+#endif
+               case IPPROTO_GRE:
+                       if (vflag)
+                               (void)printf("gre %s > %s: ",
+                                            ipaddr_string(&ip->ip_src),
+                                            ipaddr_string(&ip->ip_dst));
+                       /* do it */
+                       gre_print(cp, len);
+                       if (! vflag) {
+                               printf(" (gre encap)");
+                               return;
+                       }
+                       break;
+
+               default:
+                       (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
+                               ipaddr_string(&ip->ip_dst));
+                       (void)printf(" ip-proto-%d %d", ip->ip_p, len);
+                       break;
+               }
+       }
+       /*
+        * for fragmented datagrams, print id:size@offset.  On all
+        * but the last stick a "+".  For unfragmented datagrams, note
+        * the don't fragment flag.
+        */
+       if (off & 0x3fff) {
+               /*
+                * if this isn't the first frag, we're missing the
+                * next level protocol header.  print the ip addr.
+                */
+               if (off & 0x1fff)
+                       (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
+                                     ipaddr_string(&ip->ip_dst));
+               (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len,
+                       (off & 0x1fff) * 8,
+                       (off & IP_MF)? "+" : "");
+       } else if (off & IP_DF)
+               (void)printf(" (DF)");
+
+       if (ip->ip_tos)
+               (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
+       if (ip->ip_ttl <= 1)
+               (void)printf(" [ttl %d]", (int)ip->ip_ttl);
+
+       if (vflag) {
+               int sum;
+               char *sep = "";
+
+               printf(" (");
+               if (ip->ip_ttl > 1) {
+                       (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
+                       sep = ", ";
+               }
+               if ((off & 0x3fff) == 0) {
+                       (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
+                       sep = ", ";
+               }
+               if ((u_char *)ip + hlen <= snapend) {
+                       sum = in_cksum(ip);
+                       if (sum != 0) {
+                               (void)printf("%sbad cksum %x!", sep,
+                                            ntohs(ip->ip_sum));
+                               sep = ", ";
+                       }
+               }
+               if ((hlen -= sizeof(struct ip)) > 0) {
+                       (void)printf("%soptlen=%d", sep, hlen);
+                       ip_optprint((u_char *)(ip + 1), hlen);
+               }
+               printf(")");
+       }
+}
diff --git a/tcpdump.tproj/print-ipx.c b/tcpdump.tproj/print-ipx.c
new file mode 100644 (file)
index 0000000..f526160
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print Novell IPX packets.
+ * Contributed by Brad Parker (brad@fcr.com).
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ipx.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ipx.h"
+#include "extract.h"
+
+
+static const char *ipxaddr_string(u_int32_t, const u_char *);
+void ipx_decode(const struct ipxHdr *, const u_char *, u_int);
+void ipx_sap_print(const u_short *, u_int);
+void ipx_rip_print(const u_short *, u_int);
+
+/*
+ * Print IPX datagram packets.
+ */
+void
+ipx_print(const u_char *p, u_int length)
+{
+       const struct ipxHdr *ipx = (const struct ipxHdr *)p;
+
+       TCHECK(ipx->srcSkt);
+       (void)printf("%s.%x > ",
+                    ipxaddr_string(EXTRACT_32BITS(ipx->srcNet), ipx->srcNode),
+                    EXTRACT_16BITS(&ipx->srcSkt));
+
+       (void)printf("%s.%x:",
+                    ipxaddr_string(EXTRACT_32BITS(ipx->dstNet), ipx->dstNode),
+                    EXTRACT_16BITS(&ipx->dstSkt));
+
+       /* take length from ipx header */
+       TCHECK(ipx->length);
+       length = EXTRACT_16BITS(&ipx->length);
+
+       ipx_decode(ipx, (u_char *)ipx + ipxSize, length - ipxSize);
+       return;
+trunc:
+       printf("[|ipx %d]", length);
+}
+
+static const char *
+ipxaddr_string(u_int32_t net, const u_char *node)
+{
+    static char line[256];
+
+    sprintf(line, "%x.%02x:%02x:%02x:%02x:%02x:%02x",
+           net, node[0], node[1], node[2], node[3], node[4], node[5]);
+
+    return line;
+}
+
+void
+ipx_decode(const struct ipxHdr *ipx, const u_char *datap, u_int length)
+{
+    register u_short dstSkt;
+
+    dstSkt = EXTRACT_16BITS(&ipx->dstSkt);
+    switch (dstSkt) {
+      case IPX_SKT_NCP:
+       (void)printf(" ipx-ncp %d", length);
+       break;
+      case IPX_SKT_SAP:
+       ipx_sap_print((u_short *)datap, length);
+       break;
+      case IPX_SKT_RIP:
+       ipx_rip_print((u_short *)datap, length);
+       break;
+      case IPX_SKT_NETBIOS:
+       (void)printf(" ipx-netbios %d", length);
+       break;
+      case IPX_SKT_DIAGNOSTICS:
+       (void)printf(" ipx-diags %d", length);
+       break;
+      default:
+       (void)printf(" ipx-#%x %d", dstSkt, length);
+       break;
+    }
+}
+
+void
+ipx_sap_print(const u_short *ipx, u_int length)
+{
+    int command, i;
+
+    TCHECK(ipx[0]);
+    command = EXTRACT_16BITS(ipx);
+    ipx++;
+    length -= 2;
+
+    switch (command) {
+      case 1:
+      case 3:
+       if (command == 1)
+           (void)printf("ipx-sap-req");
+       else
+           (void)printf("ipx-sap-nearest-req");
+
+       if (length > 0) {
+           TCHECK(ipx[1]);
+           (void)printf(" %x '", EXTRACT_16BITS(&ipx[0]));
+           fn_print((u_char *)&ipx[1], (u_char *)&ipx[1] + 48);
+           putchar('\'');
+       }
+       break;
+
+      case 2:
+      case 4:
+       if (command == 2)
+           (void)printf("ipx-sap-resp");
+       else
+           (void)printf("ipx-sap-nearest-resp");
+
+       for (i = 0; i < 8 && length > 0; i++) {
+           TCHECK2(ipx[27], 1);
+           (void)printf(" %x '", EXTRACT_16BITS(&ipx[0]));
+           fn_print((u_char *)&ipx[1], (u_char *)&ipx[1] + 48);
+           printf("' addr %s",
+               ipxaddr_string(EXTRACT_32BITS(&ipx[25]), (u_char *)&ipx[27]));
+           ipx += 32;
+           length -= 64;
+       }
+       break;
+      default:
+           (void)printf("ipx-sap-?%x", command);
+       break;
+    }
+       return;
+trunc:
+       printf("[|ipx %d]", length);
+}
+
+void
+ipx_rip_print(const u_short *ipx, u_int length)
+{
+    int command, i;
+
+    TCHECK(ipx[0]);
+    command = EXTRACT_16BITS(ipx);
+    ipx++;
+    length -= 2;
+
+    switch (command) {
+      case 1:
+       (void)printf("ipx-rip-req");
+       if (length > 0) {
+           TCHECK(ipx[3]);
+           (void)printf(" %u/%d.%d", EXTRACT_32BITS(&ipx[0]),
+                        EXTRACT_16BITS(&ipx[2]), EXTRACT_16BITS(&ipx[3]));
+       }
+       break;
+      case 2:
+       (void)printf("ipx-rip-resp");
+       for (i = 0; i < 50 && length > 0; i++) {
+           TCHECK(ipx[3]);
+           (void)printf(" %u/%d.%d", EXTRACT_32BITS(&ipx[0]),
+                        EXTRACT_16BITS(&ipx[2]), EXTRACT_16BITS(&ipx[3]));
+
+           ipx += 4;
+           length -= 8;
+       }
+       break;
+      default:
+           (void)printf("ipx-rip-?%x", command);
+    }
+       return;
+trunc:
+       printf("[|ipx %d]", length);
+}
+
diff --git a/tcpdump.tproj/print-isoclns.c b/tcpdump.tproj/print-isoclns.c
new file mode 100644 (file)
index 0000000..cea4a7e
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Original code by Matt Thomas, Digital Equipment Corporation
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-isoclns.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ethertype.h"
+
+#define        CLNS    129
+#define        ESIS    130
+#define        ISIS    131
+#define        NULLNS  0
+
+static int osi_cksum(const u_char *, u_int, const u_char *, u_char *, u_char *);
+static void esis_print(const u_char *, u_int);
+
+void
+isoclns_print(const u_char *p, u_int length, u_int caplen,
+             const u_char *esrc, const u_char *edst)
+{
+       if (caplen < 1) {
+               printf("[|iso-clns] ");
+               if (!eflag)
+                       printf("%s > %s",
+                              etheraddr_string(esrc),
+                              etheraddr_string(edst));
+               return;
+       }
+
+       switch (*p) {
+
+       case CLNS:
+               /* esis_print(&p, &length); */
+               printf("iso-clns");
+               if (!eflag)
+                       (void)printf(" %s > %s",
+                                    etheraddr_string(esrc),
+                                    etheraddr_string(edst));
+               break;
+
+       case ESIS:
+               printf("iso-esis");
+               if (!eflag)
+                       (void)printf(" %s > %s",
+                                    etheraddr_string(esrc),
+                                    etheraddr_string(edst));
+               esis_print(p, length);
+               return;
+
+       case ISIS:
+               printf("iso-isis");
+               if (!eflag)
+                       (void)printf(" %s > %s",
+                                    etheraddr_string(esrc),
+                                    etheraddr_string(edst));
+               /* isis_print(&p, &length); */
+               (void)printf(" len=%d ", length);
+               if (caplen > 1)
+                       default_print_unaligned(p, caplen);
+               break;
+
+       case NULLNS:
+               printf("iso-nullns");
+               if (!eflag)
+                       (void)printf(" %s > %s",
+                                    etheraddr_string(esrc),
+                                    etheraddr_string(edst));
+               break;
+
+       default:
+               printf("iso-clns %02x", p[0]);
+               if (!eflag)
+                       (void)printf(" %s > %s",
+                                    etheraddr_string(esrc),
+                                    etheraddr_string(edst));
+               (void)printf(" len=%d ", length);
+               if (caplen > 1)
+                       default_print_unaligned(p, caplen);
+               break;
+       }
+}
+
+#define        ESIS_REDIRECT   6
+#define        ESIS_ESH        2
+#define        ESIS_ISH        4
+
+struct esis_hdr {
+       u_char version;
+       u_char reserved;
+       u_char type;
+       u_char tmo[2];
+       u_char cksum[2];
+};
+
+static void
+esis_print(const u_char *p, u_int length)
+{
+       const u_char *ep;
+       int li = p[1];
+       const struct esis_hdr *eh = (const struct esis_hdr *) &p[2];
+       u_char cksum[2];
+       u_char off[2];
+
+       if (length == 2) {
+               if (qflag)
+                       printf(" bad pkt!");
+               else
+                       printf(" no header at all!");
+               return;
+       }
+       ep = p + li;
+       if (li > length) {
+               if (qflag)
+                       printf(" bad pkt!");
+               else
+                       printf(" LI(%d) > PDU size (%d)!", li, length);
+               return;
+       }
+       if (li < sizeof(struct esis_hdr) + 2) {
+               if (qflag)
+                       printf(" bad pkt!");
+               else {
+                       printf(" too short for esis header %d:", li);
+                       while (--length >= 0)
+                               printf("%02X", *p++);
+               }
+               return;
+       }
+       switch (eh->type & 0x1f) {
+
+       case ESIS_REDIRECT:
+               printf(" redirect");
+               break;
+
+       case ESIS_ESH:
+               printf(" esh");
+               break;
+
+       case ESIS_ISH:
+               printf(" ish");
+               break;
+
+       default:
+               printf(" type %d", eh->type & 0x1f);
+               break;
+       }
+       off[0] = eh->cksum[0];
+       off[1] = eh->cksum[1];
+       if (vflag && osi_cksum(p, li, eh->cksum, cksum, off)) {
+               printf(" bad cksum (got %02x%02x want %02x%02x)",
+                      eh->cksum[1], eh->cksum[0], cksum[1], cksum[0]);
+               return;
+       }
+       if (eh->version != 1) {
+               printf(" unsupported version %d", eh->version);
+               return;
+       }
+       p += sizeof(*eh) + 2;
+       li -= sizeof(*eh) + 2;  /* protoid * li */
+
+       switch (eh->type & 0x1f) {
+       case ESIS_REDIRECT: {
+               const u_char *dst, *snpa, *is;
+
+               dst = p; p += *p + 1;
+               if (p > snapend)
+                       return;
+               printf(" %s", isonsap_string(dst));
+               snpa = p; p += *p + 1;
+               is = p;   p += *p + 1;
+               if (p > snapend)
+                       return;
+               if (p > ep) {
+                       printf(" [bad li]");
+                       return;
+               }
+               if (is[0] == 0)
+                       printf(" > %s", etheraddr_string(&snpa[1]));
+               else
+                       printf(" > %s", isonsap_string(is));
+               li = ep - p;
+               break;
+       }
+#if 0
+       case ESIS_ESH:
+               printf(" esh");
+               break;
+#endif
+       case ESIS_ISH: {
+               const u_char *is;
+
+               is = p; p += *p + 1;
+               if (p > ep) {
+                       printf(" [bad li]");
+                       return;
+               }
+               if (p > snapend)
+                       return;
+               printf(" %s", isonsap_string(is));
+               li = ep - p;
+               break;
+       }
+
+       default:
+               (void)printf(" len=%d", length);
+               if (length && p < snapend) {
+                       length = snapend - p;
+                       default_print(p, length);
+               }
+               return;
+       }
+       if (vflag)
+               while (p < ep && li) {
+                       int op, opli;
+                       const u_char *q;
+
+                       if (snapend - p < 2)
+                               return;
+                       if (li < 2) {
+                               printf(" bad opts/li");
+                               return;
+                       }
+                       op = *p++;
+                       opli = *p++;
+                       li -= 2;
+                       if (opli > li) {
+                               printf(" opt (%d) too long", op);
+                               return;
+                       }
+                       li -= opli;
+                       q = p;
+                       p += opli;
+                       if (snapend < p)
+                               return;
+                       if (op == 198 && opli == 2) {
+                               printf(" tmo=%d", q[0] * 256 + q[1]);
+                               continue;
+                       }
+                       printf (" %d:<", op);
+                       while (--opli >= 0)
+                               printf("%02x", *q++);
+                       printf (">");
+               }
+}
+
+static int
+osi_cksum(register const u_char *p, register u_int len,
+         const u_char *toff, u_char *cksum, u_char *off)
+{
+       int x, y, f = (len - ((toff - p) + 1));
+       int32_t c0 = 0, c1 = 0;
+
+       if ((cksum[0] = off[0]) == 0 && (cksum[1] = off[1]) == 0)
+               return 0;
+
+       off[0] = off[1] = 0;
+       while (--len >= 0) {
+               c0 += *p++;
+               c1 += c0;
+               c0 %= 255;
+               c1 %= 255;
+       }
+       x = (c0 * f - c1);
+       if (x < 0)
+               x = 255 - (-x % 255);
+       else
+               x %= 255;
+       y = -1 * (x + c0);
+       if (y < 0)
+               y = 255 - (-y % 255);
+       else
+               y %= 255;
+
+       off[0] = x;
+       off[1] = y;
+
+       return (off[0] != cksum[0] || off[1] != cksum[1]);
+}
diff --git a/tcpdump.tproj/print-krb.c b/tcpdump.tproj/print-krb.c
new file mode 100644 (file)
index 0000000..16116a0
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Initial contribution from John Hawkinson (jhawk@mit.edu).
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-krb.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+const u_char *c_print(register const u_char *, register const u_char *);
+const u_char *krb4_print_hdr(const u_char *);
+void krb4_print(const u_char *);
+void krb_print(const u_char *, u_int);
+
+
+#define AUTH_MSG_KDC_REQUEST                   1<<1
+#define AUTH_MSG_KDC_REPLY                     2<<1
+#define AUTH_MSG_APPL_REQUEST                  3<<1
+#define AUTH_MSG_APPL_REQUEST_MUTUAL           4<<1
+#define AUTH_MSG_ERR_REPLY                     5<<1
+#define AUTH_MSG_PRIVATE                       6<<1
+#define AUTH_MSG_SAFE                          7<<1
+#define AUTH_MSG_APPL_ERR                      8<<1
+#define AUTH_MSG_DIE                           63<<1
+
+#define KERB_ERR_OK                            0
+#define KERB_ERR_NAME_EXP                      1
+#define KERB_ERR_SERVICE_EXP                   2
+#define KERB_ERR_AUTH_EXP                      3
+#define KERB_ERR_PKT_VER                       4
+#define KERB_ERR_NAME_MAST_KEY_VER             5
+#define KERB_ERR_SERV_MAST_KEY_VER             6
+#define KERB_ERR_BYTE_ORDER                    7
+#define KERB_ERR_PRINCIPAL_UNKNOWN             8
+#define KERB_ERR_PRINCIPAL_NOT_UNIQUE          9
+#define KERB_ERR_NULL_KEY                      10
+
+struct krb {
+    u_char pvno;               /* Protocol Version */
+    u_char type;               /* Type+B */
+};
+
+static char tstr[] = " [|kerberos]";
+
+static struct tok type2str[] = {
+    { AUTH_MSG_KDC_REQUEST,            "KDC_REQUEST" },
+    { AUTH_MSG_KDC_REPLY,              "KDC_REPLY" },
+    { AUTH_MSG_APPL_REQUEST,           "APPL_REQUEST" },
+    { AUTH_MSG_APPL_REQUEST_MUTUAL,    "APPL_REQUEST_MUTUAL" },
+    { AUTH_MSG_ERR_REPLY,              "ERR_REPLY" },
+    { AUTH_MSG_PRIVATE,                        "PRIVATE" },
+    { AUTH_MSG_SAFE,                   "SAFE" },
+    { AUTH_MSG_APPL_ERR,               "APPL_ERR" },
+    { AUTH_MSG_DIE,                    "DIE" },
+    { 0,                               NULL }
+};
+
+static struct tok kerr2str[] = {
+    { KERB_ERR_OK,                     "OK" },
+    { KERB_ERR_NAME_EXP,               "NAME_EXP" },
+    { KERB_ERR_SERVICE_EXP,            "SERVICE_EXP" },
+    { KERB_ERR_AUTH_EXP,               "AUTH_EXP" },
+    { KERB_ERR_PKT_VER,                        "PKT_VER" },
+    { KERB_ERR_NAME_MAST_KEY_VER,      "NAME_MAST_KEY_VER" },
+    { KERB_ERR_SERV_MAST_KEY_VER,      "SERV_MAST_KEY_VER" },
+    { KERB_ERR_BYTE_ORDER,             "BYTE_ORDER" },
+    { KERB_ERR_PRINCIPAL_UNKNOWN,      "PRINCIPAL_UNKNOWN" },
+    { KERB_ERR_PRINCIPAL_NOT_UNIQUE,   "PRINCIPAL_NOT_UNIQUE" },
+    { KERB_ERR_NULL_KEY,               "NULL_KEY"},
+    { 0,                               NULL}
+};
+
+
+/* little endian (unaligned) to host byte order */
+/* XXX need to look at this... */
+#define vtohlp(x)          ((( ((char *)(x))[0] )      )  | \
+                            (( ((char *)(x))[1] ) <<  8)  | \
+                            (( ((char *)(x))[2] ) << 16)  | \
+                            (( ((char *)(x))[3] ) << 24))
+#define vtohsp(x)          ((( ((char *)(x))[0] )      )  | \
+                            (( ((char *)(x))[1] ) <<  8))
+/* network (big endian) (unaligned) to host byte order */
+#define ntohlp(x)          ((( ((char *)(x))[3] )      )  | \
+                            (( ((char *)(x))[2] ) <<  8)  | \
+                            (( ((char *)(x))[1] ) << 16)  | \
+                            (( ((char *)(x))[0] ) << 24))
+#define ntohsp(x)          ((( ((char *)(x))[1] )      )  | \
+                            (( ((char *)(x))[0] ) <<  8))
+
+
+
+const u_char *
+c_print(register const u_char *s, register const u_char *ep)
+{
+       register u_char c;
+       register int flag;
+
+       flag = 1;
+       while (ep == NULL || s < ep) {
+               c = *s++;
+               if (c == '\0') {
+                       flag = 0;
+                       break;
+               }
+               if (!isascii(c)) {
+                       c = toascii(c);
+                       putchar('M');
+                       putchar('-');
+               }
+               if (!isprint(c)) {
+                       c ^= 0x40;      /* DEL to ?, others to alpha */
+                       putchar('^');
+               }
+               putchar(c);
+       }
+       if (flag)
+               return NULL;
+       return(s);
+}
+
+const u_char *
+krb4_print_hdr(const u_char *cp)
+{
+       cp+=2;
+
+#define PRINT          if ((cp=c_print(cp, snapend))==NULL) goto trunc
+
+       TCHECK2(cp, 0);
+       PRINT;
+       TCHECK2(cp, 0);
+       putchar('.'); PRINT;
+       TCHECK2(cp, 0);
+       putchar('@'); PRINT;
+       return(cp);
+
+trunc:
+       fputs(tstr, stdout);
+       return(NULL);
+
+#undef PRINT
+}
+
+void
+krb4_print(const u_char *cp)
+{
+       register const struct krb *kp;
+       u_char type;
+       u_short len;
+
+#define PRINT          if ((cp=c_print(cp, snapend))==NULL) goto trunc
+/*  True if struct krb is little endian */
+#define IS_LENDIAN(kp) (((kp)->type & 0x01) != 0)
+#define KTOHSP(kp, cp) (IS_LENDIAN(kp) ? vtohsp(cp) : ntohsp(cp))
+
+       kp = (struct krb *)cp;
+
+       if ((&kp->type) >= snapend) {
+               fputs(tstr, stdout);
+               return;
+       }
+
+       type = kp->type & (0xFF << 1);
+
+       printf(" %s %s: ",
+           IS_LENDIAN(kp) ? "le" : "be", tok2str(type2str, NULL, type));
+
+       switch (type) {
+
+       case AUTH_MSG_KDC_REQUEST:
+               if ((cp = krb4_print_hdr(cp)) == NULL)
+                       return;
+                cp += 4;         /* ctime */
+                TCHECK2(cp, 0);
+                printf(" %dmin ", *cp++ * 5);
+                TCHECK2(cp, 0);
+                PRINT;
+                TCHECK2(cp, 0);
+                putchar('.');  PRINT;
+                break;
+
+       case AUTH_MSG_APPL_REQUEST:
+               cp += 2;
+               TCHECK2(cp, 0);
+               printf("v%d ", *cp++);
+               TCHECK2(cp, 0);
+               PRINT;
+               TCHECK2(cp, 0);
+               printf(" (%d)", *cp++);
+               TCHECK2(cp, 0);
+               printf(" (%d)", *cp);
+               TCHECK2(cp, 0);
+               break;
+
+       case AUTH_MSG_KDC_REPLY:
+               if ((cp = krb4_print_hdr(cp)) == NULL)
+                       return;
+               cp += 10;       /* timestamp + n + exp + kvno */
+               TCHECK2(cp, 0);
+               len = KTOHSP(kp, cp);
+               printf(" (%d)", len);
+               TCHECK2(cp, 0);
+               break;
+
+       case AUTH_MSG_ERR_REPLY:
+               if ((cp = krb4_print_hdr(cp)) == NULL)
+                       return;
+               cp += 4;          /* timestamp */
+               TCHECK2(cp, 0);
+               printf(" %s ", tok2str(kerr2str, NULL, KTOHSP(kp, cp)));
+               cp += 4;
+               TCHECK2(cp, 0);
+               PRINT;
+               break;
+
+       default:
+               fputs("(unknown)", stdout);
+               break;
+       }
+
+       return;
+trunc:
+       fputs(tstr, stdout);
+}
+
+void
+krb_print(const u_char *dat, u_int length)
+{
+       register const struct krb *kp;
+
+       kp = (struct krb *)dat;
+
+       if (dat >= snapend) {
+               fputs(tstr, stdout);
+               return;
+       }
+
+       switch (kp->pvno) {
+
+       case 1:
+       case 2:
+       case 3:
+               printf(" v%d", kp->pvno);
+               break;
+
+       case 4:
+               printf(" v%d", kp->pvno);
+               krb4_print((const u_char *)kp);
+               break;
+
+       case 106:
+       case 107:
+               fputs(" v5", stdout);
+               /* Decode ASN.1 here "someday" */
+               break;
+       }
+       return;
+}
diff --git a/tcpdump.tproj/print-llc.c b/tcpdump.tproj/print-llc.c
new file mode 100644 (file)
index 0000000..4deb6ed
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Code by Matt Thomas, Digital Equipment Corporation
+ *     with an awful lot of hacking by Jeffrey Mogul, DECWRL
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-llc.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"                   /* must come after interface.h */
+
+#include "llc.h"
+
+static struct tok cmd2str[] = {
+       { LLC_UI,       "ui" },
+       { LLC_TEST,     "test" },
+       { LLC_XID,      "xid" },
+       { LLC_UA,       "ua" },
+       { LLC_DISC,     "disc" },
+       { LLC_DM,       "dm" },
+       { LLC_SABME,    "sabme" },
+       { LLC_FRMR,     "frmr" },
+       { 0,            NULL }
+};
+
+/*
+ * Returns non-zero IFF it succeeds in printing the header
+ */
+int
+llc_print(const u_char *p, u_int length, u_int caplen,
+         const u_char *esrc, const u_char *edst)
+{
+       struct llc llc;
+       register u_short et;
+       register int ret;
+
+       if (caplen < 3) {
+               (void)printf("[|llc]");
+               default_print((u_char *)p, caplen);
+               return(0);
+       }
+
+       /* Watch out for possible alignment problems */
+       memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc)));
+
+       if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) {
+               ipx_print(p, length);
+               return (1);
+       }
+#ifdef notyet
+       else if (p[0] == 0xf0 && p[1] == 0xf0)
+               netbios_print(p, length);
+#endif
+       if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS
+           && llc.llcui == LLC_UI) {
+               isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst);
+               return (1);
+       }
+
+       if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP
+           && llc.llcui == LLC_UI) {
+               if (caplen < sizeof(llc)) {
+                   (void)printf("[|llc-snap]");
+                   default_print((u_char *)p, caplen);
+                   return (0);
+               }
+               if (vflag)
+                       (void)printf("snap %s ", protoid_string(llc.llcpi));
+
+               caplen -= sizeof(llc);
+               length -= sizeof(llc);
+               p += sizeof(llc);
+
+               /* This is an encapsulated Ethernet packet */
+               et = EXTRACT_16BITS(&llc.ethertype[0]);
+               ret = ether_encap_print(et, p, length, caplen);
+               if (ret)
+                       return (ret);
+       }
+
+       if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
+               if (eflag)
+                       (void)printf("%s ", llcsap_string(llc.dsap));
+               else
+                       (void)printf("%s > %s %s ",
+                                       etheraddr_string(esrc),
+                                       etheraddr_string(edst),
+                                       llcsap_string(llc.dsap));
+       } else {
+               if (eflag)
+                       (void)printf("%s > %s ",
+                               llcsap_string(llc.ssap & ~LLC_GSAP),
+                               llcsap_string(llc.dsap));
+               else
+                       (void)printf("%s %s > %s %s ",
+                               etheraddr_string(esrc),
+                               llcsap_string(llc.ssap & ~LLC_GSAP),
+                               etheraddr_string(edst),
+                               llcsap_string(llc.dsap));
+       }
+
+       if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
+               const char *m;
+               char f;
+               m = tok2str(cmd2str, "%02x", LLC_U_CMD(llc.llcu));
+               switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
+                   case 0:                     f = 'C'; break;
+                   case LLC_GSAP:              f = 'R'; break;
+                   case LLC_U_POLL:            f = 'P'; break;
+                   case LLC_GSAP|LLC_U_POLL:   f = 'F'; break;
+                   default:                    f = '?'; break;
+               }
+
+               printf("%s/%c", m, f);
+
+               p += 3;
+               length -= 3;
+               caplen -= 3;
+
+               if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) {
+                   if (*p == LLC_XID_FI) {
+                       printf(": %02x %02x", p[1], p[2]);
+                       p += 3;
+                       length -= 3;
+                       caplen -= 3;
+                   }
+               }
+       } else {
+               char f;
+               llc.llcis = ntohs(llc.llcis);
+               switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
+                   case 0:                     f = 'C'; break;
+                   case LLC_GSAP:              f = 'R'; break;
+                   case LLC_U_POLL:            f = 'P'; break;
+                   case LLC_GSAP|LLC_U_POLL:   f = 'F'; break;
+                   default:                    f = '?'; break;
+               }
+
+               if ((llc.llcu & LLC_S_FMT) == LLC_S_FMT) {
+                       static char *llc_s[] = { "rr", "rej", "rnr", "03" };
+                       (void)printf("%s (r=%d,%c)",
+                               llc_s[LLC_S_CMD(llc.llcis)],
+                               LLC_IS_NR(llc.llcis),
+                               f);
+               } else {
+                       (void)printf("I (s=%d,r=%d,%c)",
+                               LLC_I_NS(llc.llcis),
+                               LLC_IS_NR(llc.llcis),
+                               f);
+               }
+               p += 4;
+               length -= 4;
+               caplen -= 4;
+       }
+       (void)printf(" len=%d", length);
+       if (caplen > 0) {
+               default_print_unaligned(p, caplen);
+       }
+       return(1);
+}
diff --git a/tcpdump.tproj/print-netbios.c b/tcpdump.tproj/print-netbios.c
new file mode 100644 (file)
index 0000000..fdf16a3
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print NETBIOS packets.
+ * Contributed by Brad Parker (brad@fcr.com).
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-netbios.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "netbios.h"
+#include "extract.h"
+
+/*
+ * Print NETBIOS packets.
+ */
+void
+netbios_print(struct p8022Hdr *nb, u_int length)
+{
+       if (length < p8022Size) {
+               (void)printf(" truncated-netbios %d", length);
+               return;
+       }
+
+       if (nb->flags == UI) {
+           (void)printf("802.1 UI ");
+       } else {
+           (void)printf("802.1 CONN ");
+       }
+
+       if ((u_char *)(nb + 1) > snapend) {
+               printf(" [|netbios]");
+               return;
+       }
+
+/*
+       netbios_decode(nb, (u_char *)nb + p8022Size, length - p8022Size);
+*/
+}
+
+#ifdef never
+       (void)printf("%s.%d > ",
+                    ipxaddr_string(EXTRACT_32BITS(ipx->srcNet), ipx->srcNode),
+                    EXTRACT_16BITS(ipx->srcSkt));
+
+       (void)printf("%s.%d:",
+                    ipxaddr_string(EXTRACT_32BITS(ipx->dstNet), ipx->dstNode),
+                    EXTRACT_16BITS(ipx->dstSkt));
+
+       if ((u_char *)(ipx + 1) > snapend) {
+               printf(" [|ipx]");
+               return;
+       }
+
+       /* take length from ipx header */
+       length = EXTRACT_16BITS(&ipx->length);
+
+       ipx_decode(ipx, (u_char *)ipx + ipxSize, length - ipxSize);
+#endif
+
diff --git a/tcpdump.tproj/print-nfs.c b/tcpdump.tproj/print-nfs.c
new file mode 100644 (file)
index 0000000..9f7b5b2
--- /dev/null
@@ -0,0 +1,891 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-nfs.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <rpc/rpc.h>
+
+#include <ctype.h>
+#include <pcap.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+#include "nfsv2.h"
+#include "nfsfh.h"
+
+static void nfs_printfh(const u_int32_t *);
+static void xid_map_enter(const struct rpc_msg *, const struct ip *);
+static int32_t xid_map_find(const struct rpc_msg *, const struct ip *);
+static void interp_reply(const struct rpc_msg *, u_int32_t, u_int);
+
+static int nfserr;             /* true if we error rather than trunc */
+
+void
+nfsreply_print(register const u_char *bp, u_int length,
+              register const u_char *bp2)
+{
+       register const struct rpc_msg *rp;
+       register const struct ip *ip;
+       int32_t proc;
+
+       nfserr = 0;             /* assume no error */
+       rp = (const struct rpc_msg *)bp;
+       ip = (const struct ip *)bp2;
+
+       if (!nflag)
+               (void)printf("%s.nfs > %s.%x: reply %s %d",
+                            ipaddr_string(&ip->ip_src),
+                            ipaddr_string(&ip->ip_dst),
+                            (u_int32_t)ntohl(rp->rm_xid),
+                            ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED?
+                                    "ok":"ERR",
+                            length);
+       else
+               (void)printf("%s.%x > %s.%x: reply %s %d",
+                            ipaddr_string(&ip->ip_src),
+                            NFS_PORT,
+                            ipaddr_string(&ip->ip_dst),
+                            (u_int32_t)ntohl(rp->rm_xid),
+                            ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED?
+                               "ok":"ERR",
+                            length);
+
+       proc = xid_map_find(rp, ip);
+       if (proc >= 0)
+               interp_reply(rp, (u_int32_t)proc, length);
+}
+
+/*
+ * Return a pointer to the first file handle in the packet.
+ * If the packet was truncated, return 0.
+ */
+static const u_int32_t *
+parsereq(register const struct rpc_msg *rp, register u_int length)
+{
+       register const u_int32_t *dp;
+       register u_int len;
+
+       /*
+        * find the start of the req data (if we captured it)
+        */
+       dp = (u_int32_t *)&rp->rm_call.cb_cred;
+       TCHECK(dp[1]);
+       len = ntohl(dp[1]);
+       if (len < length) {
+               dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
+               TCHECK(dp[1]);
+               len = ntohl(dp[1]);
+               if (len < length) {
+                       dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
+                       TCHECK2(dp[0], 0);
+                       return (dp);
+               }
+       }
+trunc:
+       return (NULL);
+}
+
+/*
+ * Print out an NFS file handle and return a pointer to following word.
+ * If packet was truncated, return 0.
+ */
+static const u_int32_t *
+parsefh(register const u_int32_t *dp)
+{
+       if (dp + 8 <= (u_int32_t *)snapend) {
+               nfs_printfh(dp);
+               return (dp + 8);
+       }
+       return (NULL);
+}
+
+/*
+ * Print out a file name and return pointer to 32-bit word past it.
+ * If packet was truncated, return 0.
+ */
+static const u_int32_t *
+parsefn(register const u_int32_t *dp)
+{
+       register u_int32_t len;
+       register const u_char *cp;
+
+       /* Bail if we don't have the string length */
+       if ((u_char *)dp > snapend - sizeof(*dp))
+               return (NULL);
+
+       /* Fetch string length; convert to host order */
+       len = *dp++;
+       NTOHL(len);
+
+       cp = (u_char *)dp;
+       /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */
+       dp += ((len + 3) & ~3) / sizeof(*dp);
+       if ((u_char *)dp > snapend)
+               return (NULL);
+       /* XXX seems like we should be checking the length */
+       putchar('"');
+       (void) fn_printn(cp, len, NULL);
+       putchar('"');
+
+       return (dp);
+}
+
+/*
+ * Print out file handle and file name.
+ * Return pointer to 32-bit word past file name.
+ * If packet was truncated (or there was some other error), return 0.
+ */
+static const u_int32_t *
+parsefhn(register const u_int32_t *dp)
+{
+       dp = parsefh(dp);
+       if (dp == NULL)
+               return (NULL);
+       putchar(' ');
+       return (parsefn(dp));
+}
+
+void
+nfsreq_print(register const u_char *bp, u_int length,
+    register const u_char *bp2)
+{
+       register const struct rpc_msg *rp;
+       register const struct ip *ip;
+       register const u_int32_t *dp;
+
+       nfserr = 0;             /* assume no error */
+       rp = (const struct rpc_msg *)bp;
+       ip = (const struct ip *)bp2;
+       if (!nflag)
+               (void)printf("%s.%x > %s.nfs: %d",
+                            ipaddr_string(&ip->ip_src),
+                            (u_int32_t)ntohl(rp->rm_xid),
+                            ipaddr_string(&ip->ip_dst),
+                            length);
+       else
+               (void)printf("%s.%x > %s.%x: %d",
+                            ipaddr_string(&ip->ip_src),
+                            (u_int32_t)ntohl(rp->rm_xid),
+                            ipaddr_string(&ip->ip_dst),
+                            NFS_PORT,
+                            length);
+
+       xid_map_enter(rp, ip);  /* record proc number for later on */
+
+       switch (ntohl(rp->rm_call.cb_proc)) {
+#ifdef NFSPROC_NOOP
+       case NFSPROC_NOOP:
+               printf(" nop");
+               return;
+#else
+#define NFSPROC_NOOP -1
+#endif
+       case NFSPROC_NULL:
+               printf(" null");
+               return;
+
+       case NFSPROC_GETATTR:
+               printf(" getattr");
+               if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL)
+                       return;
+               break;
+
+       case NFSPROC_SETATTR:
+               printf(" setattr");
+               if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL)
+                       return;
+               break;
+
+#if NFSPROC_ROOT != NFSPROC_NOOP
+       case NFSPROC_ROOT:
+               printf(" root");
+               break;
+#endif
+       case NFSPROC_LOOKUP:
+               printf(" lookup");
+               if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL)
+                       return;
+               break;
+
+       case NFSPROC_READLINK:
+               printf(" readlink");
+               if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL)
+                       return;
+               break;
+
+       case NFSPROC_READ:
+               printf(" read");
+               if ((dp = parsereq(rp, length)) != NULL &&
+                   (dp = parsefh(dp)) != NULL) {
+                       TCHECK2(dp[0], 3 * sizeof(*dp));
+                       printf(" %u bytes @ %u",
+                           (u_int32_t)ntohl(dp[1]),
+                           (u_int32_t)ntohl(dp[0]));
+                       return;
+               }
+               break;
+
+#if NFSPROC_WRITECACHE != NFSPROC_NOOP
+       case NFSPROC_WRITECACHE:
+               printf(" writecache");
+               if ((dp = parsereq(rp, length)) != NULL &&
+                   (dp = parsefh(dp)) != NULL) {
+                       TCHECK2(dp[0], 4 * sizeof(*dp));
+                       printf(" %u (%u) bytes @ %u (%u)",
+                           (u_int32_t)ntohl(dp[3]),
+                           (u_int32_t)ntohl(dp[2]),
+                           (u_int32_t)ntohl(dp[1]),
+                           (u_int32_t)ntohl(dp[0]));
+                       return;
+               }
+               break;
+#endif
+       case NFSPROC_WRITE:
+               printf(" write");
+               if ((dp = parsereq(rp, length)) != NULL &&
+                   (dp = parsefh(dp)) != NULL) {
+                       TCHECK2(dp[0], 4 * sizeof(*dp));
+                       printf(" %u (%u) bytes @ %u (%u)",
+                           (u_int32_t)ntohl(dp[3]),
+                           (u_int32_t)ntohl(dp[2]),
+                           (u_int32_t)ntohl(dp[1]),
+                           (u_int32_t)ntohl(dp[0]));
+                       return;
+               }
+               break;
+
+       case NFSPROC_CREATE:
+               printf(" create");
+               if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL)
+                       return;
+               break;
+
+       case NFSPROC_REMOVE:
+               printf(" remove");
+               if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL)
+                       return;
+               break;
+
+       case NFSPROC_RENAME:
+               printf(" rename");
+               if ((dp = parsereq(rp, length)) != NULL &&
+                   (dp = parsefhn(dp)) != NULL) {
+                       fputs(" ->", stdout);
+                       if (parsefhn(dp) != NULL)
+                               return;
+               }
+               break;
+
+       case NFSPROC_LINK:
+               printf(" link");
+               if ((dp = parsereq(rp, length)) != NULL &&
+                   (dp = parsefh(dp)) != NULL) {
+                       fputs(" ->", stdout);
+                       if (parsefhn(dp) != NULL)
+                               return;
+               }
+               break;
+
+       case NFSPROC_SYMLINK:
+               printf(" symlink");
+               if ((dp = parsereq(rp, length)) != NULL &&
+                   (dp = parsefhn(dp)) != NULL) {
+                       fputs(" -> ", stdout);
+                       if (parsefn(dp) != NULL)
+                               return;
+               }
+               break;
+
+       case NFSPROC_MKDIR:
+               printf(" mkdir");
+               if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL)
+                       return;
+               break;
+
+       case NFSPROC_RMDIR:
+               printf(" rmdir");
+               if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL)
+                       return;
+               break;
+
+       case NFSPROC_READDIR:
+               printf(" readdir");
+               if ((dp = parsereq(rp, length)) != NULL &&
+                   (dp = parsefh(dp)) != NULL) {
+                       TCHECK2(dp[0], 2 * sizeof(*dp));
+                       /*
+                        * Print the offset as signed, since -1 is common,
+                        * but offsets > 2^31 aren't.
+                        */
+                       printf(" %u bytes @ %d",
+                           (u_int32_t)ntohl(dp[1]),
+                           (u_int32_t)ntohl(dp[0]));
+                       return;
+               }
+               break;
+
+       case NFSPROC_STATFS:
+               printf(" statfs");
+               if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL)
+                       return;
+               break;
+
+       default:
+               printf(" proc-%u", (u_int32_t)ntohl(rp->rm_call.cb_proc));
+               return;
+       }
+trunc:
+       if (!nfserr)
+               fputs(" [|nfs]", stdout);
+}
+
+/*
+ * Print out an NFS file handle.
+ * We assume packet was not truncated before the end of the
+ * file handle pointed to by dp.
+ *
+ * Note: new version (using portable file-handle parser) doesn't produce
+ * generation number.  It probably could be made to do that, with some
+ * additional hacking on the parser code.
+ */
+static void
+nfs_printfh(register const u_int32_t *dp)
+{
+       my_fsid fsid;
+       ino_t ino;
+       char *sfsname = NULL;
+
+       Parse_fh((caddr_t *)dp, &fsid, &ino, NULL, &sfsname, 0);
+
+       if (sfsname) {
+               /* file system ID is ASCII, not numeric, for this server OS */
+               static char temp[NFS_FHSIZE+1];
+
+               /* Make sure string is null-terminated */
+               strncpy(temp, sfsname, NFS_FHSIZE);
+               /* Remove trailing spaces */
+               sfsname = strchr(temp, ' ');
+               if (sfsname)
+                       *sfsname = 0;
+
+               (void)printf(" fh %s/%u", temp, (u_int32_t)ino);
+       } else {
+               (void)printf(" fh %u,%u/%u",
+                   fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor, (u_int32_t)ino);
+       }
+}
+
+/*
+ * Maintain a small cache of recent client.XID.server/proc pairs, to allow
+ * us to match up replies with requests and thus to know how to parse
+ * the reply.
+ */
+
+struct xid_map_entry {
+       u_int32_t               xid;            /* transaction ID (net order) */
+       struct in_addr  client;         /* client IP address (net order) */
+       struct in_addr  server;         /* server IP address (net order) */
+       u_int32_t               proc;           /* call proc number (host order) */
+};
+
+/*
+ * Map entries are kept in an array that we manage as a ring;
+ * new entries are always added at the tail of the ring.  Initially,
+ * all the entries are zero and hence don't match anything.
+ */
+
+#define        XIDMAPSIZE      64
+
+struct xid_map_entry xid_map[XIDMAPSIZE];
+
+int    xid_map_next = 0;
+int    xid_map_hint = 0;
+
+static void
+xid_map_enter(const struct rpc_msg *rp, const struct ip *ip)
+{
+       struct xid_map_entry *xmep;
+
+       xmep = &xid_map[xid_map_next];
+
+       if (++xid_map_next >= XIDMAPSIZE)
+               xid_map_next = 0;
+
+       xmep->xid = rp->rm_xid;
+       xmep->client = ip->ip_src;
+       xmep->server = ip->ip_dst;
+       xmep->proc = ntohl(rp->rm_call.cb_proc);
+}
+
+/* Returns NFSPROC_xxx or -1 on failure */
+static int32_t
+xid_map_find(const struct rpc_msg *rp, const struct ip *ip)
+{
+       int i;
+       struct xid_map_entry *xmep;
+       u_int32_t xid = rp->rm_xid;
+       u_int32_t clip = ip->ip_dst.s_addr;
+       u_int32_t sip = ip->ip_src.s_addr;
+
+       /* Start searching from where we last left off */
+       i = xid_map_hint;
+       do {
+               xmep = &xid_map[i];
+               if (xmep->xid == xid && xmep->client.s_addr == clip &&
+                   xmep->server.s_addr == sip) {
+                       /* match */
+                       xid_map_hint = i;
+                       return ((int32_t)xmep->proc);
+               }
+               if (++i >= XIDMAPSIZE)
+                       i = 0;
+       } while (i != xid_map_hint);
+
+       /* search failed */
+       return (-1);
+}
+
+/*
+ * Routines for parsing reply packets
+ */
+
+/*
+ * Return a pointer to the beginning of the actual results.
+ * If the packet was truncated, return 0.
+ */
+static const u_int32_t *
+parserep(register const struct rpc_msg *rp, register u_int length)
+{
+       register const u_int32_t *dp;
+       u_int len;
+       enum accept_stat astat;
+
+       /*
+        * Portability note:
+        * Here we find the address of the ar_verf credentials.
+        * Originally, this calculation was
+        *      dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf
+        * On the wire, the rp_acpt field starts immediately after
+        * the (32 bit) rp_stat field.  However, rp_acpt (which is a
+        * "struct accepted_reply") contains a "struct opaque_auth",
+        * whose internal representation contains a pointer, so on a
+        * 64-bit machine the compiler inserts 32 bits of padding
+        * before rp->rm_reply.rp_acpt.ar_verf.  So, we cannot use
+        * the internal representation to parse the on-the-wire
+        * representation.  Instead, we skip past the rp_stat field,
+        * which is an "enum" and so occupies one 32-bit word.
+        */
+       dp = ((const u_int32_t *)&rp->rm_reply) + 1;
+       TCHECK2(dp[0], 1);
+       len = ntohl(dp[1]);
+       if (len >= length)
+               return (NULL);
+       /*
+        * skip past the ar_verf credentials.
+        */
+       dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t);
+       TCHECK2(dp[0], 0);
+
+       /*
+        * now we can check the ar_stat field
+        */
+       astat = ntohl(*(enum accept_stat *)dp);
+       switch (astat) {
+
+       case SUCCESS:
+               break;
+
+       case PROG_UNAVAIL:
+               printf(" PROG_UNAVAIL");
+               nfserr = 1;             /* suppress trunc string */
+               return (NULL);
+
+       case PROG_MISMATCH:
+               printf(" PROG_MISMATCH");
+               nfserr = 1;             /* suppress trunc string */
+               return (NULL);
+
+       case PROC_UNAVAIL:
+               printf(" PROC_UNAVAIL");
+               nfserr = 1;             /* suppress trunc string */
+               return (NULL);
+
+       case GARBAGE_ARGS:
+               printf(" GARBAGE_ARGS");
+               nfserr = 1;             /* suppress trunc string */
+               return (NULL);
+
+       case SYSTEM_ERR:
+               printf(" SYSTEM_ERR");
+               nfserr = 1;             /* suppress trunc string */
+               return (NULL);
+
+       default:
+               printf(" ar_stat %d", astat);
+               nfserr = 1;             /* suppress trunc string */
+               return (NULL);
+       }
+       /* successful return */
+       if ((sizeof(astat) + ((u_char *)dp)) < snapend)
+               return ((u_int32_t *) (sizeof(astat) + ((char *)dp)));
+
+trunc:
+       return (NULL);
+}
+
+static const u_int32_t *
+parsestatus(const u_int32_t *dp)
+{
+       register int errnum;
+
+       TCHECK(dp[0]);
+       errnum = ntohl(dp[0]);
+       if (errnum != 0) {
+               if (!qflag)
+                       printf(" ERROR: %s", pcap_strerror(errnum));
+               nfserr = 1;             /* suppress trunc string */
+               return (NULL);
+       }
+       return (dp + 1);
+trunc:
+       return (NULL);
+}
+
+static struct tok type2str[] = {
+       { NFNON,        "NON" },
+       { NFREG,        "REG" },
+       { NFDIR,        "DIR" },
+       { NFBLK,        "BLK" },
+       { NFCHR,        "CHR" },
+       { NFLNK,        "LNK" },
+       { 0,            NULL }
+};
+
+static const u_int32_t *
+parsefattr(const u_int32_t *dp, int verbose)
+{
+       const struct nfsv2_fattr *fap;
+
+       fap = (const struct nfsv2_fattr *)dp;
+       if (verbose) {
+               TCHECK(fap->fa_nfssize);
+               printf(" %s %o ids %u/%u sz %u ",
+                   tok2str(type2str, "unk-ft %d ",
+                   (u_int32_t)ntohl(fap->fa_type)),
+                   (u_int32_t)ntohl(fap->fa_mode),
+                   (u_int32_t)ntohl(fap->fa_uid),
+                   (u_int32_t)ntohl(fap->fa_gid),
+                   (u_int32_t)ntohl(fap->fa_nfssize));
+       }
+       /* print lots more stuff */
+       if (verbose > 1) {
+               TCHECK(fap->fa_nfsfileid);
+               printf("nlink %u rdev %x fsid %x nodeid %x a/m/ctime ",
+                   (u_int32_t)ntohl(fap->fa_nlink),
+                   (u_int32_t)ntohl(fap->fa_nfsrdev),
+                   (u_int32_t)ntohl(fap->fa_nfsfsid),
+                   (u_int32_t)ntohl(fap->fa_nfsfileid));
+               TCHECK(fap->fa_nfsatime);
+               printf("%u.%06u ",
+                   (u_int32_t)ntohl(fap->fa_nfsatime.nfs_sec),
+                   (u_int32_t)ntohl(fap->fa_nfsatime.nfs_usec));
+               TCHECK(fap->fa_nfsmtime);
+               printf("%u.%06u ",
+                   (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_sec),
+                   (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_usec));
+               TCHECK(fap->fa_nfsctime);
+               printf("%u.%06u ",
+                   (u_int32_t)ntohl(fap->fa_nfsctime.nfs_sec),
+                   (u_int32_t)ntohl(fap->fa_nfsctime.nfs_usec));
+       }
+       return ((const u_int32_t *)&fap[1]);
+trunc:
+       return (NULL);
+}
+
+static int
+parseattrstat(const u_int32_t *dp, int verbose)
+{
+
+       dp = parsestatus(dp);
+       if (dp == NULL)
+               return (0);
+
+       return (parsefattr(dp, verbose) != NULL);
+}
+
+static int
+parsediropres(const u_int32_t *dp)
+{
+
+       dp = parsestatus(dp);
+       if (dp == NULL)
+               return (0);
+
+       dp = parsefh(dp);
+       if (dp == NULL)
+               return (0);
+
+       return (parsefattr(dp, vflag) != NULL);
+}
+
+static int
+parselinkres(const u_int32_t *dp)
+{
+       dp = parsestatus(dp);
+       if (dp == NULL)
+               return (0);
+
+       putchar(' ');
+       return (parsefn(dp) != NULL);
+}
+
+static int
+parsestatfs(const u_int32_t *dp)
+{
+       const struct nfsv2_statfs *sfsp;
+
+       dp = parsestatus(dp);
+       if (dp == NULL)
+               return (0);
+
+       if (!qflag) {
+               sfsp = (const struct nfsv2_statfs *)dp;
+               TCHECK(sfsp->sf_bavail);
+               printf(" tsize %u bsize %u blocks %u bfree %u bavail %u",
+                   (u_int32_t)ntohl(sfsp->sf_tsize),
+                   (u_int32_t)ntohl(sfsp->sf_bsize),
+                   (u_int32_t)ntohl(sfsp->sf_blocks),
+                   (u_int32_t)ntohl(sfsp->sf_bfree),
+                   (u_int32_t)ntohl(sfsp->sf_bavail));
+       }
+
+       return (1);
+trunc:
+       return (0);
+}
+
+static int
+parserddires(const u_int32_t *dp)
+{
+       dp = parsestatus(dp);
+       if (dp == NULL)
+               return (0);
+       if (!qflag) {
+               TCHECK(dp[0]);
+               printf(" offset %x", (u_int32_t)ntohl(dp[0]));
+               TCHECK(dp[1]);
+               printf(" size %u", (u_int32_t)ntohl(dp[1]));
+               TCHECK(dp[2]);
+               if (dp[2] != 0)
+                       printf(" eof");
+       }
+
+       return (1);
+trunc:
+       return (0);
+}
+
+static void
+interp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int length)
+{
+       register const u_int32_t *dp;
+
+       switch (proc) {
+
+#ifdef NFSPROC_NOOP
+       case NFSPROC_NOOP:
+               printf(" nop");
+               return;
+#else
+#define NFSPROC_NOOP -1
+#endif
+       case NFSPROC_NULL:
+               printf(" null");
+               return;
+
+       case NFSPROC_GETATTR:
+               printf(" getattr");
+               dp = parserep(rp, length);
+               if (dp != NULL && parseattrstat(dp, !qflag) != 0)
+                       return;
+               break;
+
+       case NFSPROC_SETATTR:
+               printf(" setattr");
+               dp = parserep(rp, length);
+               if (dp != NULL && parseattrstat(dp, !qflag) != 0)
+                       return;
+               break;
+
+#if NFSPROC_ROOT != NFSPROC_NOOP
+       case NFSPROC_ROOT:
+               printf(" root");
+               break;
+#endif
+       case NFSPROC_LOOKUP:
+               printf(" lookup");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsediropres(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_READLINK:
+               printf(" readlink");
+               dp = parserep(rp, length);
+               if (dp != NULL && parselinkres(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_READ:
+               printf(" read");
+               dp = parserep(rp, length);
+               if (dp != NULL && parseattrstat(dp, vflag) != 0)
+                       return;
+               break;
+
+#if NFSPROC_WRITECACHE != NFSPROC_NOOP
+       case NFSPROC_WRITECACHE:
+               printf(" writecache");
+               break;
+#endif
+       case NFSPROC_WRITE:
+               printf(" write");
+               dp = parserep(rp, length);
+               if (dp != NULL && parseattrstat(dp, vflag) != 0)
+                       return;
+               break;
+
+       case NFSPROC_CREATE:
+               printf(" create");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsediropres(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_REMOVE:
+               printf(" remove");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsestatus(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_RENAME:
+               printf(" rename");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsestatus(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_LINK:
+               printf(" link");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsestatus(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_SYMLINK:
+               printf(" symlink");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsestatus(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_MKDIR:
+               printf(" mkdir");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsediropres(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_RMDIR:
+               printf(" rmdir");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsestatus(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_READDIR:
+               printf(" readdir");
+               dp = parserep(rp, length);
+               if (dp != NULL && parserddires(dp) != 0)
+                       return;
+               break;
+
+       case NFSPROC_STATFS:
+               printf(" statfs");
+               dp = parserep(rp, length);
+               if (dp != NULL && parsestatfs(dp) != 0)
+                       return;
+               break;
+
+       default:
+               printf(" proc-%u", proc);
+               return;
+       }
+       if (!nfserr)
+               fputs(" [|nfs]", stdout);
+}
diff --git a/tcpdump.tproj/print-ntp.c b/tcpdump.tproj/print-ntp.c
new file mode 100644 (file)
index 0000000..52931a7
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print ntp packets.
+ *     By Jeffrey Mogul/DECWRL
+ *     loosely based on print-bootp.c
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ntp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#undef MODEMASK                                        /* Solaris sucks */
+#include "ntp.h"
+
+static void p_sfix(const struct s_fixedpt *);
+static void p_ntp_time(const struct l_fixedpt *);
+static void p_ntp_delta(const struct l_fixedpt *, const struct l_fixedpt *);
+
+/*
+ * Print ntp requests
+ */
+void
+ntp_print(register const u_char *cp, u_int length)
+{
+       register const struct ntpdata *bp;
+       int mode, version, leapind;
+       static char rclock[5];
+
+       bp = (struct ntpdata *)cp;
+       /* Note funny sized packets */
+       if (length != sizeof(struct ntpdata))
+               (void)printf(" [len=%d]", length);
+
+       TCHECK(bp->status);
+
+       version = (int)(bp->status & VERSIONMASK) >> 3;
+       printf(" v%d", version);
+
+       leapind = bp->status & LEAPMASK;
+       switch (leapind) {
+
+       case NO_WARNING:
+               break;
+
+       case PLUS_SEC:
+               fputs(" +1s", stdout);
+               break;
+
+       case MINUS_SEC:
+               fputs(" -1s", stdout);
+               break;
+       }
+
+       mode = bp->status & MODEMASK;
+       switch (mode) {
+
+       case MODE_UNSPEC:       /* unspecified */
+               fputs(" unspec", stdout);
+               break;
+
+       case MODE_SYM_ACT:      /* symmetric active */
+               fputs(" sym_act", stdout);
+               break;
+
+       case MODE_SYM_PAS:      /* symmetric passive */
+               fputs(" sym_pas", stdout);
+               break;
+
+       case MODE_CLIENT:       /* client */
+               fputs(" client", stdout);
+               break;
+
+       case MODE_SERVER:       /* server */
+               fputs(" server", stdout);
+               break;
+
+       case MODE_BROADCAST:    /* broadcast */
+               fputs(" bcast", stdout);
+               break;
+
+       case MODE_RES1:         /* reserved */
+               fputs(" res1", stdout);
+               break;
+
+       case MODE_RES2:         /* reserved */
+               fputs(" res2", stdout);
+               break;
+
+       }
+
+       TCHECK(bp->stratum);
+       printf(" strat %d", bp->stratum);
+
+       TCHECK(bp->ppoll);
+       printf(" poll %d", bp->ppoll);
+
+       /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */
+       TCHECK2(bp->distance, 0);
+       printf(" prec %d", bp->precision);
+
+       if (!vflag)
+               return;
+
+       TCHECK(bp->distance);
+       fputs(" dist ", stdout);
+       p_sfix(&bp->distance);
+
+       TCHECK(bp->dispersion);
+       fputs(" disp ", stdout);
+       p_sfix(&bp->dispersion);
+
+       TCHECK(bp->refid);
+       fputs(" ref ", stdout);
+       /* Interpretation depends on stratum */
+       switch (bp->stratum) {
+
+       case UNSPECIFIED:
+               printf("(unspec)");
+               break;
+
+       case PRIM_REF:
+               strncpy(rclock, (char *)&(bp->refid), 4);
+               rclock[4] = '\0';
+               fputs(rclock, stdout);
+               break;
+
+       case INFO_QUERY:
+               printf("%s INFO_QUERY", ipaddr_string(&(bp->refid)));
+               /* this doesn't have more content */
+               return;
+
+       case INFO_REPLY:
+               printf("%s INFO_REPLY", ipaddr_string(&(bp->refid)));
+               /* this is too complex to be worth printing */
+               return;
+
+       default:
+               printf("%s", ipaddr_string(&(bp->refid)));
+               break;
+       }
+
+       TCHECK(bp->reftime);
+       putchar('@');
+       p_ntp_time(&(bp->reftime));
+
+       TCHECK(bp->org);
+       fputs(" orig ", stdout);
+       p_ntp_time(&(bp->org));
+
+       TCHECK(bp->rec);
+       fputs(" rec ", stdout);
+       p_ntp_delta(&(bp->org), &(bp->rec));
+
+       TCHECK(bp->xmt);
+       fputs(" xmt ", stdout);
+       p_ntp_delta(&(bp->org), &(bp->xmt));
+
+       return;
+
+trunc:
+       fputs(" [|ntp]", stdout);
+}
+
+static void
+p_sfix(register const struct s_fixedpt *sfp)
+{
+       register int i;
+       register int f;
+       register float ff;
+
+       i = ntohs(sfp->int_part);
+       f = ntohs(sfp->fraction);
+       ff = f / 65536.0;       /* shift radix point by 16 bits */
+       f = ff * 1000000.0;     /* Treat fraction as parts per million */
+       printf("%d.%06d", i, f);
+}
+
+#define        FMAXINT (4294967296.0)  /* floating point rep. of MAXINT */
+
+static void
+p_ntp_time(register const struct l_fixedpt *lfp)
+{
+       register int32_t i;
+       register u_int32_t uf;
+       register u_int32_t f;
+       register float ff;
+
+       i = ntohl(lfp->int_part);
+       uf = ntohl(lfp->fraction);
+       ff = uf;
+       if (ff < 0.0)           /* some compilers are buggy */
+               ff += FMAXINT;
+       ff = ff / FMAXINT;      /* shift radix point by 32 bits */
+       f = ff * 1000000000.0;  /* treat fraction as parts per billion */
+       printf("%u.%09d", i, f);
+}
+
+/* Prints time difference between *lfp and *olfp */
+static void
+p_ntp_delta(register const struct l_fixedpt *olfp,
+           register const struct l_fixedpt *lfp)
+{
+       register int32_t i;
+       register u_int32_t uf;
+       register u_int32_t ouf;
+       register u_int32_t f;
+       register float ff;
+       int signbit;
+
+       i = ntohl(lfp->int_part) - ntohl(olfp->int_part);
+
+       uf = ntohl(lfp->fraction);
+       ouf = ntohl(olfp->fraction);
+
+       if (i > 0) {            /* new is definitely greater than old */
+               signbit = 0;
+               f = uf - ouf;
+               if (ouf > uf)   /* must borrow from high-order bits */
+                       i -= 1;
+       } else if (i < 0) {     /* new is definitely less than old */
+               signbit = 1;
+               f = ouf - uf;
+               if (uf > ouf)   /* must carry into the high-order bits */
+                       i += 1;
+               i = -i;
+       } else {                /* int_part is zero */
+               if (uf > ouf) {
+                       signbit = 0;
+                       f = uf - ouf;
+               } else {
+                       signbit = 1;
+                       f = ouf - uf;
+               }
+       }
+
+       ff = f;
+       if (ff < 0.0)           /* some compilers are buggy */
+               ff += FMAXINT;
+       ff = ff / FMAXINT;      /* shift radix point by 32 bits */
+       f = ff * 1000000000.0;  /* treat fraction as parts per billion */
+       if (signbit)
+               putchar('-');
+       else
+               putchar('+');
+       printf("%d.%09d", i, f);
+}
diff --git a/tcpdump.tproj/print-null.c b/tcpdump.tproj/print-null.c
new file mode 100644 (file)
index 0000000..7dcf69b
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-null.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <pcap.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "addrtoname.h"
+#include "interface.h"
+
+#define        NULL_HDRLEN 4
+
+#ifndef AF_NS
+#define AF_NS          6               /* XEROX NS protocols */
+#endif
+
+static void
+null_print(const u_char *p, const struct ip *ip, u_int length)
+{
+       u_int family;
+
+       memcpy((char *)&family, (char *)p, sizeof(family));
+
+       if (nflag) {
+               /* XXX just dump the header */
+               return;
+       }
+       switch (family) {
+
+       case AF_INET:
+               printf("ip: ");
+               break;
+
+       case AF_NS:
+               printf("ns: ");
+               break;
+
+       default:
+               printf("AF %d: ", family);
+               break;
+       }
+}
+
+void
+null_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       u_int length = h->len;
+       u_int caplen = h->caplen;
+       const struct ip *ip;
+
+       ts_print(&h->ts);
+
+       /*
+        * Some printers want to get back at the link level addresses,
+        * and/or check that they're not walking off the end of the packet.
+        * Rather than pass them all the way down, we set these globals.
+        */
+       packetp = p;
+       snapend = p + caplen;
+
+       length -= NULL_HDRLEN;
+
+       ip = (struct ip *)(p + NULL_HDRLEN);
+
+       if (eflag)
+               null_print(p, ip, length);
+
+       ip_print((const u_char *)ip, length);
+
+       if (xflag)
+               default_print((const u_char *)ip, caplen - NULL_HDRLEN);
+       putchar('\n');
+}
+
diff --git a/tcpdump.tproj/print-ospf.c b/tcpdump.tproj/print-ospf.c
new file mode 100644 (file)
index 0000000..5012fb8
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ospf.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <ctype.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+#include "ospf.h"
+
+struct bits {
+       u_int32_t bit;
+       const char *str;
+};
+
+static const struct bits ospf_option_bits[] = {
+       { OSPF_OPTION_T,        "T" },
+       { OSPF_OPTION_E,        "E" },
+       { OSPF_OPTION_MC,       "MC" },
+       { 0,                    NULL }
+};
+
+static const struct bits ospf_rla_flag_bits[] = {
+       { RLA_FLAG_B,           "B" },
+       { RLA_FLAG_E,           "E" },
+       { RLA_FLAG_W1,          "W1" },
+       { RLA_FLAG_W2,          "W2" },
+       { 0,                    NULL }
+};
+
+static struct tok type2str[] = {
+       { OSPF_TYPE_UMD,        "umd" },
+       { OSPF_TYPE_HELLO,      "hello" },
+       { OSPF_TYPE_DB,         "dd" },
+       { OSPF_TYPE_LSR,        "ls_req" },
+       { OSPF_TYPE_LSU,        "ls_upd" },
+       { OSPF_TYPE_LSA,        "ls_ack" },
+       { 0,                    NULL }
+};
+
+static char tstr[] = " [|ospf]";
+
+/* Forwards */
+static inline void ospf_print_seqage(u_int32_t, time_t);
+static inline void ospf_print_bits(const struct bits *, u_char);
+static void ospf_print_ls_type(u_int, const struct in_addr *,
+    const struct in_addr *, const char *);
+static int ospf_print_lshdr(const struct lsa_hdr *);
+static int ospf_print_lsa(const struct lsa *);
+static int ospf_decode_v2(const struct ospfhdr *, const u_char *);
+
+static inline void
+ospf_print_seqage(register u_int32_t seq, register time_t us)
+{
+       register time_t sec = us % 60;
+       register time_t mins = (us / 60) % 60;
+       register time_t hour = us / 3600;
+
+       printf(" S %X age ", seq);
+       if (hour)
+               printf("%u:%02u:%02u",
+                   (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec);
+       else if (mins)
+               printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec);
+       else
+               printf("%u", (u_int32_t) sec);
+}
+
+
+static inline void
+ospf_print_bits(register const struct bits *bp, register u_char options)
+{
+       register char sep = ' ';
+
+       do {
+               if (options & bp->bit) {
+                       printf("%c%s", sep, bp->str);
+                       sep = '/';
+               }
+       } while ((++bp)->bit);
+}
+
+static void
+ospf_print_ls_type(register u_int ls_type,
+    register const struct in_addr *ls_stateid,
+    register const struct in_addr *ls_router, register const char *fmt)
+{
+
+       switch (ls_type) {
+
+       case LS_TYPE_ROUTER:
+               printf(" rtr %s ", ipaddr_string(ls_router));
+               break;
+
+       case LS_TYPE_NETWORK:
+               printf(" net dr %s if %s",
+                   ipaddr_string(ls_router),
+                   ipaddr_string(ls_stateid));
+               break;
+
+       case LS_TYPE_SUM_IP:
+               printf(" sum %s abr %s",
+                   ipaddr_string(ls_stateid),
+                   ipaddr_string(ls_router));
+               break;
+
+       case LS_TYPE_SUM_ABR:
+               printf(" abr %s rtr %s",
+                   ipaddr_string(ls_router),
+                   ipaddr_string(ls_stateid));
+               break;
+
+       case LS_TYPE_ASE:
+               printf(" ase %s asbr %s",
+                   ipaddr_string(ls_stateid),
+                   ipaddr_string(ls_router));
+               break;
+
+       case LS_TYPE_GROUP:
+               printf(" group %s rtr %s",
+                   ipaddr_string(ls_stateid),
+                   ipaddr_string(ls_router));
+               break;
+
+       default:
+               putchar(' ');
+               printf(fmt, ls_type);
+               break;
+       }
+}
+
+static int
+ospf_print_lshdr(register const struct lsa_hdr *lshp)
+{
+
+       TCHECK(lshp->ls_type);
+       printf(" {");                                           /* } (ctags) */
+
+       TCHECK(lshp->ls_options);
+       ospf_print_bits(ospf_option_bits, lshp->ls_options);
+       TCHECK(lshp->ls_seq);
+       ospf_print_seqage(ntohl(lshp->ls_seq), ntohs(lshp->ls_age));
+       ospf_print_ls_type(lshp->ls_type, &lshp->ls_stateid, &lshp->ls_router,
+           "ls_type %d");
+
+       return (0);
+trunc:
+       return (1);
+}
+
+
+/*
+ * Print a single link state advertisement.  If truncated return 1, else 0.
+ */
+static int
+ospf_print_lsa(register const struct lsa *lsap)
+{
+       register const u_char *ls_end;
+       register const struct rlalink *rlp;
+       register const struct tos_metric *tosp;
+       register const struct in_addr *ap;
+       register const struct aslametric *almp;
+       register const struct mcla *mcp;
+       register const u_int32_t *lp;
+       register int j, k;
+
+       if (ospf_print_lshdr(&lsap->ls_hdr))
+               return (1);
+       TCHECK(lsap->ls_hdr.ls_length);
+       ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length);
+       switch (lsap->ls_hdr.ls_type) {
+
+       case LS_TYPE_ROUTER:
+               TCHECK(lsap->lsa_un.un_rla.rla_flags);
+               ospf_print_bits(ospf_rla_flag_bits,
+                   lsap->lsa_un.un_rla.rla_flags);
+
+               TCHECK(lsap->lsa_un.un_rla.rla_count);
+               j = ntohs(lsap->lsa_un.un_rla.rla_count);
+               TCHECK(lsap->lsa_un.un_rla.rla_link);
+               rlp = lsap->lsa_un.un_rla.rla_link;
+               while (j--) {
+                       register struct rlalink *rln =
+                           (struct rlalink *)((u_char *)(rlp + 1) +
+                           ((rlp->link_toscount) * sizeof(*tosp)));
+
+                       TCHECK(*rln);
+                       printf(" {");                           /* } (ctags) */
+                       switch (rlp->link_type) {
+
+                       case RLA_TYPE_VIRTUAL:
+                               printf(" virt");
+                               /* Fall through */
+
+                       case RLA_TYPE_ROUTER:
+                               printf(" nbrid %s if %s",
+                                   ipaddr_string(&rlp->link_id),
+                                   ipaddr_string(&rlp->link_data));
+                               break;
+
+                       case RLA_TYPE_TRANSIT:
+                               printf(" dr %s if %s",
+                                   ipaddr_string(&rlp->link_id),
+                                   ipaddr_string(&rlp->link_data));
+                               break;
+
+                       case RLA_TYPE_STUB:
+                               printf(" net %s mask %s",
+                                   ipaddr_string(&rlp->link_id),
+                                   ipaddr_string(&rlp->link_data));
+                               break;
+
+                       default:
+                                                               /* { (ctags) */
+                               printf(" ??RouterLinksType %d?? }",
+                                   rlp->link_type);
+                               return (0);
+                       }
+                       printf(" tos 0 metric %d", ntohs(rlp->link_tos0metric));
+                       tosp = (struct tos_metric *)
+                           ((sizeof rlp->link_tos0metric) + (u_char *) rlp);
+                       for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) {
+                               TCHECK(*tosp);
+                               printf(" tos %d metric %d",
+                                   tosp->tos_type,
+                                   ntohs(tosp->tos_metric));
+                       }
+                                                               /* { (ctags) */
+                       printf(" }");
+                       rlp = rln;
+               }
+               break;
+
+       case LS_TYPE_NETWORK:
+               TCHECK(lsap->lsa_un.un_nla.nla_mask);
+               printf(" mask %s rtrs",
+                   ipaddr_string(&lsap->lsa_un.un_nla.nla_mask));
+               ap = lsap->lsa_un.un_nla.nla_router;
+               while ((u_char *)ap < ls_end) {
+                       TCHECK(*ap);
+                       printf(" %s", ipaddr_string(ap));
+                       ++ap;
+               }
+               break;
+
+       case LS_TYPE_SUM_IP:
+               TCHECK(lsap->lsa_un.un_nla.nla_mask);
+               printf(" mask %s",
+                   ipaddr_string(&lsap->lsa_un.un_sla.sla_mask));
+               /* Fall through */
+
+       case LS_TYPE_SUM_ABR:
+               TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
+               lp = lsap->lsa_un.un_sla.sla_tosmetric;
+               while ((u_char *)lp < ls_end) {
+                       register u_int32_t ul;
+
+                       TCHECK(*lp);
+                       ul = ntohl(*lp);
+                       printf(" tos %d metric %d",
+                           (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
+                           ul & SLA_MASK_METRIC);
+                       ++lp;
+               }
+               break;
+
+       case LS_TYPE_ASE:
+               TCHECK(lsap->lsa_un.un_nla.nla_mask);
+               printf(" mask %s",
+                   ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
+
+               TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
+               almp = lsap->lsa_un.un_asla.asla_metric;
+               while ((u_char *)almp < ls_end) {
+                       register u_int32_t ul;
+
+                       TCHECK(almp->asla_tosmetric);
+                       ul = ntohl(almp->asla_tosmetric);
+                       printf(" type %d tos %d metric %d",
+                           (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1,
+                           (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS,
+                           (ul & ASLA_MASK_METRIC));
+                       TCHECK(almp->asla_forward);
+                       if (almp->asla_forward.s_addr) {
+                               printf(" forward %s",
+                                   ipaddr_string(&almp->asla_forward));
+                       }
+                       TCHECK(almp->asla_tag);
+                       if (almp->asla_tag.s_addr) {
+                               printf(" tag %s",
+                                   ipaddr_string(&almp->asla_tag));
+                       }
+                       ++almp;
+               }
+               break;
+
+       case LS_TYPE_GROUP:
+               /* Multicast extensions as of 23 July 1991 */
+               mcp = lsap->lsa_un.un_mcla;
+               while ((u_char *)mcp < ls_end) {
+                       TCHECK(mcp->mcla_vid);
+                       switch (ntohl(mcp->mcla_vtype)) {
+
+                       case MCLA_VERTEX_ROUTER:
+                               printf(" rtr rtrid %s",
+                                   ipaddr_string(&mcp->mcla_vid));
+                               break;
+
+                       case MCLA_VERTEX_NETWORK:
+                               printf(" net dr %s",
+                                   ipaddr_string(&mcp->mcla_vid));
+                               break;
+
+                       default:
+                               printf(" ??VertexType %u??",
+                                   (u_int32_t)ntohl(mcp->mcla_vtype));
+                               break;
+                       }
+               ++mcp;
+               }
+       }
+
+                                                               /* { (ctags) */
+       fputs(" }", stdout);
+       return (0);
+trunc:
+       fputs(" }", stdout);
+       return (1);
+}
+
+static int
+ospf_decode_v2(register const struct ospfhdr *op,
+    register const u_char *dataend)
+{
+       register const struct in_addr *ap;
+       register const struct lsr *lsrp;
+       register const struct lsa_hdr *lshp;
+       register const struct lsa *lsap;
+       register char sep;
+       register int i;
+
+       switch (op->ospf_type) {
+
+       case OSPF_TYPE_UMD:
+               /*
+                * Rob Coltun's special monitoring packets;
+                * do nothing
+                */
+               break;
+
+       case OSPF_TYPE_HELLO:
+               if (vflag) {
+                       TCHECK(op->ospf_hello.hello_deadint);
+                       ospf_print_bits(ospf_option_bits,
+                           op->ospf_hello.hello_options);
+                       printf(" mask %s int %d pri %d dead %u",
+                           ipaddr_string(&op->ospf_hello.hello_mask),
+                           ntohs(op->ospf_hello.hello_helloint),
+                           op->ospf_hello.hello_priority,
+                           (u_int32_t)ntohl(op->ospf_hello.hello_deadint));
+               }
+               TCHECK(op->ospf_hello.hello_dr);
+               if (op->ospf_hello.hello_dr.s_addr != 0)
+                       printf(" dr %s",
+                           ipaddr_string(&op->ospf_hello.hello_dr));
+               TCHECK(op->ospf_hello.hello_bdr);
+               if (op->ospf_hello.hello_bdr.s_addr != 0)
+                       printf(" bdr %s",
+                           ipaddr_string(&op->ospf_hello.hello_bdr));
+               if (vflag) {
+                       printf(" nbrs");
+                       ap = op->ospf_hello.hello_neighbor;
+                       while ((u_char *)ap < dataend) {
+                               TCHECK(*ap);
+                               printf(" %s", ipaddr_string(ap));
+                               ++ap;
+                       }
+               }
+               break;  /* HELLO */
+
+       case OSPF_TYPE_DB:
+               TCHECK(op->ospf_db.db_options);
+               ospf_print_bits(ospf_option_bits, op->ospf_db.db_options);
+               sep = ' ';
+               TCHECK(op->ospf_db.db_flags);
+               if (op->ospf_db.db_flags & OSPF_DB_INIT) {
+                       printf("%cI", sep);
+                       sep = '/';
+               }
+               if (op->ospf_db.db_flags & OSPF_DB_MORE) {
+                       printf("%cM", sep);
+                       sep = '/';
+               }
+               if (op->ospf_db.db_flags & OSPF_DB_MASTER) {
+                       printf("%cMS", sep);
+                       sep = '/';
+               }
+               TCHECK(op->ospf_db.db_seq);
+               printf(" S %X", (u_int32_t)ntohl(op->ospf_db.db_seq));
+
+               if (vflag) {
+                       /* Print all the LS adv's */
+                       lshp = op->ospf_db.db_lshdr;
+
+                       while (!ospf_print_lshdr(lshp)) {
+                                                       /* { (ctags) */
+                               printf(" }");
+                               ++lshp;
+                       }
+               }
+               break;
+
+       case OSPF_TYPE_LSR:
+               if (vflag) {
+                       lsrp = op->ospf_lsr;
+                       while ((u_char *)lsrp < dataend) {
+                               TCHECK(*lsrp);
+                               printf(" {");           /* } (ctags) */
+                               ospf_print_ls_type(ntohl(lsrp->ls_type),
+                                   &lsrp->ls_stateid,
+                                   &lsrp->ls_router,
+                                   "LinkStateType %d");
+                                                       /* { (ctags) */
+                               printf(" }");
+                               ++lsrp;
+                       }
+               }
+               break;
+
+       case OSPF_TYPE_LSU:
+               if (vflag) {
+                       lsap = op->ospf_lsu.lsu_lsa;
+                       TCHECK(op->ospf_lsu.lsu_count);
+                       i = ntohl(op->ospf_lsu.lsu_count);
+                       while (i--) {
+                               if (ospf_print_lsa(lsap))
+                                       goto trunc;
+                               lsap = (struct lsa *)((u_char *)lsap +
+                                   ntohs(lsap->ls_hdr.ls_length));
+                       }
+               }
+               break;
+
+
+       case OSPF_TYPE_LSA:
+               if (vflag) {
+                       lshp = op->ospf_lsa.lsa_lshdr;
+
+                       while (!ospf_print_lshdr(lshp)) {
+                                                       /* { (ctags) */
+                               printf(" }");
+                               ++lshp;
+                       }
+               }
+               break;
+
+       default:
+               printf("v2 type %d", op->ospf_type);
+               break;
+       }
+       return (0);
+trunc:
+       return (1);
+}
+
+void
+ospf_print(register const u_char *bp, register u_int length,
+    register const u_char *bp2)
+{
+       register const struct ospfhdr *op;
+       register const struct ip *ip;
+       register const u_char *dataend;
+       register const char *cp;
+
+       op = (struct ospfhdr *)bp;
+       ip = (struct ip *)bp2;
+       /* Print the source and destination address  */
+       (void) printf("%s > %s:",
+           ipaddr_string(&ip->ip_src),
+           ipaddr_string(&ip->ip_dst));
+
+       /* If the type is valid translate it, or just print the type */
+       /* value.  If it's not valid, say so and return */
+       TCHECK(op->ospf_type);
+       cp = tok2str(type2str, "type%d", op->ospf_type);
+       printf(" OSPFv%d-%s %d:", op->ospf_version, cp, length);
+       if (*cp == 't')
+               return;
+
+       TCHECK(op->ospf_len);
+       if (length != ntohs(op->ospf_len)) {
+               printf(" [len %d]", ntohs(op->ospf_len));
+               return;
+       }
+       dataend = bp + length;
+
+       /* Print the routerid if it is not the same as the source */
+       TCHECK(op->ospf_routerid);
+       if (ip->ip_src.s_addr != op->ospf_routerid.s_addr)
+               printf(" rtrid %s", ipaddr_string(&op->ospf_routerid));
+
+       TCHECK(op->ospf_areaid);
+       if (op->ospf_areaid.s_addr != 0)
+               printf(" area %s", ipaddr_string(&op->ospf_areaid));
+       else
+               printf(" backbone");
+
+       if (vflag) {
+               /* Print authentication data (should we really do this?) */
+               TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata));
+               switch (ntohs(op->ospf_authtype)) {
+
+               case OSPF_AUTH_NONE:
+                       break;
+
+               case OSPF_AUTH_SIMPLE:
+                       printf(" auth \"");
+                       (void)fn_printn(op->ospf_authdata,
+                           sizeof(op->ospf_authdata), NULL);
+                       printf("\"");
+                       break;
+
+               default:
+                       printf(" ??authtype-%d??", ntohs(op->ospf_authtype));
+                       return;
+               }
+       }
+       /* Do rest according to version.         */
+       switch (op->ospf_version) {
+
+       case 2:
+               /* ospf version 2 */
+               if (ospf_decode_v2(op, dataend))
+                       goto trunc;
+               break;
+
+       default:
+               printf(" ospf [version %d]", op->ospf_version);
+               break;
+       }                       /* end switch on version */
+
+       return;
+trunc:
+       fputs(tstr, stdout);
+}
diff --git a/tcpdump.tproj/print-pim.c b/tcpdump.tproj/print-pim.c
new file mode 100644 (file)
index 0000000..3fb9909
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-pim.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+void
+pim_print(register const u_char *bp, register u_int len)
+{
+    register const u_char *ep;
+    register u_char type;
+
+    ep = (const u_char *)snapend;
+    if (bp >= ep)
+       return;
+
+    type = bp[1];
+
+    switch (type) {
+    case 0:
+       (void)printf(" Query");
+       break;
+
+    case 1:
+       (void)printf(" Register");
+       break;
+
+    case 2:
+       (void)printf(" Register-Stop");
+       break;
+
+    case 3:
+       (void)printf(" Join/Prune");
+       break;
+
+    case 4:
+       (void)printf(" RP-reachable");
+       break;
+
+    case 5:
+       (void)printf(" Assert");
+       break;
+
+    case 6:
+       (void)printf(" Graft");
+       break;
+
+    case 7:
+       (void)printf(" Graft-ACK");
+       break;
+
+    case 8:
+       (void)printf(" Mode");
+       break;
+
+    default:
+       (void)printf(" [type %d]", type);
+       break;
+    }
+}
diff --git a/tcpdump.tproj/print-ppp.c b/tcpdump.tproj/print-ppp.c
new file mode 100644 (file)
index 0000000..9fd2a49
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ppp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#ifdef PPP
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <pcap.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/* XXX This goes somewhere else. */
+#define PPP_HDRLEN 4
+
+void
+ppp_if_print(u_char *user, const struct pcap_pkthdr *h,
+            register const u_char *p)
+{
+       register u_int length = h->len;
+       register u_int caplen = h->caplen;
+       const struct ip *ip;
+
+       ts_print(&h->ts);
+
+       if (caplen < PPP_HDRLEN) {
+               printf("[|ppp]");
+               goto out;
+       }
+
+       /*
+        * Some printers want to get back at the link level addresses,
+        * and/or check that they're not walking off the end of the packet.
+        * Rather than pass them all the way down, we set these globals.
+        */
+       packetp = p;
+       snapend = p + caplen;
+
+       if (eflag)
+               printf("%c %4d %02x %04x: ", p[0] ? 'O' : 'I', length,
+                      p[1], ntohs(*(u_short *)&p[2]));
+
+       length -= PPP_HDRLEN;
+       ip = (struct ip *)(p + PPP_HDRLEN);
+       ip_print((const u_char *)ip, length);
+
+       if (xflag)
+               default_print((const u_char *)ip, caplen - PPP_HDRLEN);
+out:
+       putchar('\n');
+}
+#else
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+
+#include "interface.h"
+void
+ppp_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       error("not configured for ppp");
+       /* NOTREACHED */
+}
+#endif
diff --git a/tcpdump.tproj/print-rip.c b/tcpdump.tproj/print-rip.c
new file mode 100644 (file)
index 0000000..7c87af7
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-rip.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"                   /* must come after interface.h */
+
+struct rip {
+       u_char rip_cmd;                 /* request/response */
+       u_char rip_vers;                /* protocol version # */
+       u_short rip_zero2;              /* unused */
+};
+#define        RIPCMD_REQUEST          1       /* want info */
+#define        RIPCMD_RESPONSE         2       /* responding to request */
+#define        RIPCMD_TRACEON          3       /* turn tracing on */
+#define        RIPCMD_TRACEOFF         4       /* turn it off */
+#define        RIPCMD_POLL             5       /* want info from everybody */
+#define        RIPCMD_POLLENTRY        6       /* poll for entry */
+
+struct rip_netinfo {
+       u_short rip_family;
+       u_short rip_tag;
+       u_int32_t rip_dest;
+       u_int32_t rip_dest_mask;
+       u_int32_t rip_router;
+       u_int32_t rip_metric;           /* cost of route */
+};
+
+static void
+rip_entry_print(register int vers, register const struct rip_netinfo *ni)
+{
+       register u_char *cp, *ep;
+
+       if (EXTRACT_16BITS(&ni->rip_family) != AF_INET) {
+
+               printf(" [family %d:", EXTRACT_16BITS(&ni->rip_family));
+               cp = (u_char *)&ni->rip_tag;
+               ep = (u_char *)&ni->rip_metric + sizeof(ni->rip_metric);
+               for (; cp < ep; cp += 2)
+                       printf(" %04x", EXTRACT_16BITS(cp));
+               printf("]");
+       } else if (vers < 2) {
+               /* RFC 1058 */
+               printf(" %s", ipaddr_string(&ni->rip_dest));
+       } else {
+               /* RFC 1723 */
+               printf(" {%s", ipaddr_string(&ni->rip_dest));
+               if (ni->rip_dest_mask)
+                       printf("/%s", ipaddr_string(&ni->rip_dest_mask));
+               if (ni->rip_router)
+                       printf("->%s", ipaddr_string(&ni->rip_router));
+               if (ni->rip_tag)
+                       printf(" tag %04x", EXTRACT_16BITS(&ni->rip_tag));
+               printf("}");
+       }
+       printf("(%d)", EXTRACT_32BITS(&ni->rip_metric));
+}
+
+void
+rip_print(const u_char *dat, u_int length)
+{
+       register const struct rip *rp;
+       register const struct rip_netinfo *ni;
+       register int i, j, trunc;
+
+       i = min(length, snapend - dat) - sizeof(*rp);
+       if (i < 0)
+               return;
+
+       rp = (struct rip *)dat;
+       switch (rp->rip_cmd) {
+
+       case RIPCMD_REQUEST:
+               printf(" rip-req %d", length);
+               break;
+
+       case RIPCMD_RESPONSE:
+               j = length / sizeof(*ni);
+               if (j * sizeof(*ni) != length - 4)
+                       printf(" rip-resp %d[%d]:", j, length);
+               else
+                       printf(" rip-resp %d:", j);
+               trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i);
+               ni = (struct rip_netinfo *)(rp + 1);
+               for (; (i -= sizeof(*ni)) >= 0; ++ni)
+                       rip_entry_print(rp->rip_vers, ni);
+               if (trunc)
+                       printf("[|rip]");
+               break;
+
+       case RIPCMD_TRACEON:
+               printf(" rip-traceon %d: \"", length);
+               (void)fn_print((const u_char *)(rp + 1), snapend);
+               fputs("\"\n", stdout);
+               break;
+
+       case RIPCMD_TRACEOFF:
+               printf(" rip-traceoff %d", length);
+               break;
+
+       case RIPCMD_POLL:
+               printf(" rip-poll %d", length);
+               break;
+
+       case RIPCMD_POLLENTRY:
+               printf(" rip-pollentry %d", length);
+               break;
+
+       default:
+               printf(" rip-#%d %d", rp->rip_cmd, length);
+               break;
+       }
+       switch (rp->rip_vers) {
+
+       case 1:
+       case 2:
+               break;
+
+       default:
+               printf(" [vers %d]", rp->rip_vers);
+               break;
+        }
+}
diff --git a/tcpdump.tproj/print-skip.c b/tcpdump.tproj/print-skip.c
new file mode 100644 (file)
index 0000000..d9f5059
--- /dev/null
@@ -0,0 +1,943 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: print-skip.c,v 1.2 1996/07/13 11:01:29 mickey Exp $   */
+
+/*
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+
+ * IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * SUN MICROSYSTEMS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+
+ * SUN MICROSYSTEMS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND SUN
+ * MICROSYSTEMS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
+ * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+*/
+
+#include <sys/param.h> 
+#include <sys/time.h> 
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+#define MAX_ALGS               (256)
+
+int skipflag = 0;
+
+const int       skip_max_algs = MAX_ALGS;
+
+char            *old_skip_crypt_algs[MAX_ALGS] = {
+                                        "none",         /* 0 */
+                                        "des_cbc",      /* 1 */
+                                        "rc2_cbc",      /* 2 */
+                                        "rc4(40bit)",   /* 3 */
+                                        "rc4(128bit)",  /* 4 */
+                                        "des_ede-2",    /* 5 */
+                                        "des_ede-3",    /* 6 */
+                                        "idea",         /* 7 */
+                                        "",             /* 8 */
+                                        "",             /* 9 */
+                                        "simplecrypt"   /* 10 */
+                };
+
+
+char *
+skip_alg_to_name(char *table[], int alg)
+{
+        if (alg > skip_max_algs) {
+                return ("<invalid>");
+        }
+        if (alg < 0) {
+                return ("<invalid>");
+        }
+        if (table[alg] == NULL) {
+                return ("<unknown>");
+        }
+        if (strlen(table[alg]) == 0) {
+                return ("<unknown>");
+        }
+        return (table[alg]);
+}
+
+/*
+ * This is what an OLD skip encrypted-authenticated packet looks like:
+ *
+ *
+ *                 0       1      2      3
+ *            ---------------------------------
+ *            |                               |
+ *            /      Clear IP Header          /  
+ *            |                               |     IP protocol = IPSP
+ *            ---------------------------------
+ *            |                               |
+ *            |         IPSP header           |  
+ *            |                               |
+ *            ---------------------------------
+ *            |                               |
+ *            /    Protected  IPSP Payload    /
+ *            /                               /
+ *            |                               |
+ *            ---------------------------------
+ *
+ *
+ * The format of the IPSP header for encrypted-encapsulated mode is shown below. * The fields are transmitted from left to right.
+ *
+ *   0                   1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  | Ver.  |E|A|C|S|B|R|               zero                        |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    Kij alg.   |   Kp alg.     |        reserved               |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    Optional boxid field                                       |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    Kp encrypted in Kij...          (typically 8-16 bytes)
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    Message Indicator (e.g IV)...   (typically 8-16 bytes)
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |    Protected IPSP Payload...
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *
+ *   Field values:
+ *   Ver.: protocol version
+ *   E:    1 if packet is encrypted, 0 otherwise
+ *   A:    1 if packet is authenticated, 0 otherwise
+ *   C:    1 if packet is compressed before encryption, 0 otherwise
+ *   S:    1 if packet is sequenced, 0 otherwise
+ *   B:    1 if packet is tunneled (header contains boxid), 0 otherwise
+ *   R:    reserved (should be 0 until specified)
+ *
+ */
+/*
+ * per-algorithm encrytped key sizes...
+ */
+unsigned char   old_skip_ekp_sizes[MAX_ALGS] = {
+                          8,    /* plaintext */
+                          8,    /* DES */
+                          8,    /* RC2 */
+                          8,    /* RC4 (40 bit)  */
+                         16,    /* RC4 (128 bit) */
+                         16,    /* 3DES 2 */
+                         24,    /* 3DES 3 */
+                         16,    /* IDEA */
+                          0,    /* */
+                          0,    /* */
+                          8,    /* simplecrypt */
+                };
+/*
+ * per-algorithm message indicator sizes...
+ */
+unsigned char   old_skip_mid_sizes[MAX_ALGS] = {
+                          8,    /* plaintext */
+                          8,    /* DES */
+                          8,    /* RC2 */
+                          8,    /* RC4 40 bit */
+                          8,    /* RC4 128 bit */
+                          8,    /* 3DES 2 */
+                          8,    /* 3DES 3 */
+                          8,    /* IDEA */
+                          0,    /* */
+                          0,    /* */
+                          8,    /* simplecrypt */
+                };
+
+void skip_print_old(register const u_char *bp, register int length, 
+                                                       const u_char *bp2)
+{
+       struct ip *ip;
+       const u_char *end;
+       u_char *p;
+       unsigned char   kij_alg, kp_alg, *c;
+       unsigned short i;
+       unsigned short len;
+       int boxid;
+       int node;
+
+       ip=(struct ip *)bp2;
+       p=(u_char *)bp;
+       end=bp+length;
+       printf("SKIP: *** OLD SKIP ***\n");
+       printf("OSKIP: %s>%s:%d",ipaddr_string(&ip->ip_src),
+                              ipaddr_string(&ip->ip_dst),length);
+       if (!skipflag)
+               return;
+       printf("\nOSKIP: SAID byte 1= 0x%02x\n",*p);
+       printf("OSKIP:    xxxx .... = version %d\n", (int) (*p & 0xf0) >> 4);
+        if (*p & 0x08) {
+                printf("OSKIP:    .... 1... = encrypted\n");
+        } else {
+                printf("OSKIP:    .... 0... = not encrypted\n");
+        }
+        if (*p & 0x04) {
+                printf("OSKIP:    .... .1.. = authenticated\n");
+        } else {
+                printf("OSKIP:    .... .0.. = not authenticated\n");
+        }
+        if (*p & 0x02) {
+                printf("OSKIP:    .... ..1. = compressed\n");
+        } else {
+                printf("OSKIP:    .... ..0. = not compressed\n");
+        }
+        if (*p & 0x01) {
+                printf("OSKIP:    .... ...1 = sequenced\n");
+        } else {
+                printf("OSKIP:    .... ...0 = not sequenced\n");
+        }
+                           
+        p++;
+
+       printf("OSKIP: SAID byte 2 = 0x%02x\n", *p);
+        if (*p & 0x80) {
+               node=1;
+                printf("OSKIP:    1... .... = Node ID present\n");
+        } else {
+               node=0;
+                printf("OSKIP:    0... .... = no Node ID present\n");
+        }
+        if (*p & 0x40) {
+                printf("OSKIP:    .1.. .... = <reserved should be zero>\n");
+        } else {
+                printf("OSKIP:    .0.. .... = <reserved should be zero>\n");
+        }
+        if (*p & 0x20) {
+                printf("OSKIP:    ..1. .... = <reserved should be zero>\n");
+        } else {
+                printf("OSKIP:    ..0. .... = <reserved should be zero>\n");
+        }
+        if (*p & 0x10) {
+                printf("OSKIP:    ...1 .... = <reserved should be zero>\n");
+        } else {
+                printf("OSKIP:    ...0 .... = <reserved should be zero>\n");
+        }
+         p++;
+        printf("OSKIP: SAID byte 3 = 0x%02x\n", *p);
+        p++;     
+        printf("OSKIP: SAID byte 4 = 0x%02x\n", *p);
+        p++;
+        kij_alg = *p;
+        printf("OSKIP: Kij alg (key encryption algorithm) = 0x%02x (%s)\n",
+                   kij_alg, skip_alg_to_name(old_skip_crypt_algs,kij_alg));
+        p++;
+        kp_alg = *p;
+        printf("OSKIP: Kp alg (traffic encryption algorithm) = 0x%02x (%s)\n",
+                   kp_alg, skip_alg_to_name(old_skip_crypt_algs,kp_alg));
+        p++;
+        /*
+         * the skip reserved field
+         */
+        printf("OSKIP: reserved byte 1 = 0x%02x\n", *p++);
+        printf("OSKIP: reserved byte 2 = 0x%02x\n", *p++);
+
+        if (node) {
+        /*
+         * boxid field
+         */
+           if ((end - p) < sizeof(boxid)) {
+                   return;
+           }
+           c = (unsigned char *) &boxid;
+           *c++ = *p++;
+           *c++ = *p++;
+           *c++ = *p++;
+           *c++ = *p++;
+
+           printf("OSKIP: Node ID = 0x%08x\n", ntohl(boxid));
+        }
+
+        /*
+         * encrypted kp (ekp) field
+         */
+
+        /*
+         * do this with a for-loop to avoid alignment problems and the
+         * overhead of calling bcopy()
+         */
+        len     = old_skip_ekp_sizes[kp_alg];
+        if ((unsigned short) (end - p) < len) {
+                return;
+        }
+
+        printf("OSKIP: encrypted Kp:  ");
+        for (i = 0; i < len; i++) {
+                printf("%02x ", (unsigned char) *p++);
+        }
+        printf("\n");
+
+        /*
+         * message indicator (mid) field
+         */
+        len     = old_skip_mid_sizes[kp_alg];
+        if ((unsigned short) (end - p) < len) {
+                return;
+        }
+        printf("OSKIP: message indicator field:  ");
+        for (i = 0; i < len; i++) {
+                printf("%02x ", (unsigned char) *p++);
+        }
+        printf("\n");
+}
+
+
+
+/* 
+ * The following part is (c) by G. Caronni  -- 29.11.95 
+ *
+ * This code is in the public domain; do with it what you wish.
+ *
+ * NO WARRANTY, NO SUPPORT, NO NOTHING!
+ */
+
+
+/*
+ * This is what a NEW skip encrypted-authenticated packet looks like:
+ *
+ *
+ *                 0       1      2      3
+ *            ---------------------------------
+ *            |                               |
+ *            /      Clear IP Header          /  
+ *            |                               |     IP protocol = SKIP
+ *            ---------------------------------
+ *            |                               |
+ *            |         SKIP header           |  
+ *            |                               |
+ *            ---------------------------------
+ *            |                               |
+ *            |    Auth Header & payload      |  
+ *            |                               |
+ *            ---------------------------------
+ *            |                               |
+ *            |    ESP header and SPI         |  
+ *            |                               |
+ *            ---------------------------------
+ *            |                               |
+ *            /    Protected  ESP Payload     /
+ *            |                               |
+ *            ---------------------------------
+ *
+ *
+ * The format of the SKIP header for encrypted-encapsulated mode is shown below. * The fields are transmitted from left to right.
+ *
+ *    0                   1                   2                   3
+ *    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |  Ver  | Rsvd  | Source NSID   | Dest NSID     | NEXT HEADER   |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |                    Counter n                                  |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |    Kij Alg    |   Crypt Alg   |  MAC Alg      |  Comp Alg     |
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |    Kp encrypted in Kijn...          (typically 8-16 bytes)
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |    Source Master Key-ID  (If Source NSID is non-zero)
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |    Destination Master Key-ID (If Dest NSID is non-zero)
+ *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+
+
+
+
+/*
+ * per name space key ID sizes...
+ */
+unsigned char   skip_nsid_sizes[MAX_ALGS] = {
+                          0,    /* 0  none */
+                          4,    /* 1  IP v4 Address Space */
+                          4,    /* 2  POSIX/XOPEN User Ids */
+                         16,    /* 3  IPv6 Address Space */
+                         16,    /* 4  MD5 of DNS Names */
+                         16,    /* 5  MD5 of ISO ASN.1 DN encoding */
+                         16,    /* 6  MD5 of US Social Security number */
+                          6,    /* 7  802.x MAC Address */
+                         16,    /* 8  MD5 of public Value */
+                         16,    /* 9  MD5 of RFC822 Mailbox Address */
+                         16,    /* 10 MD5 of Bank Account # */
+                         16,    /* 11 MD5 of NIS Name */
+                };
+
+
+/*
+ * per Kp algorithm encrypted Kp sizes... (Kij alg does not matter for now)
+ */
+unsigned char   skip_ekp_sizes[MAX_ALGS] = {
+                          0,    /* 0 plaintext */
+                          8,    /* 1 DES_CBC */
+                          24,   /* 2 3 key triple DES-EDE-CBC */
+                          0,    /* 3  */
+                          0,    /* 4  */
+                          0,    /* 5  */
+                          0,    /* 6  */
+                          0,    /* 7  */
+                          0,    /* 8  */
+                          0,    /* 9  */                        /* 10 .. 249 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                         8,    /* 250 RC4-40 */                          
+                         16,   /* 251 RC4-128 */                          
+                         8,    /* 252 simple crypt */                          
+                         16,   /* 253 IDEA */                          
+                         0,    /* 254 */                          
+                         0     /* 255 */                          
+                };
+
+
+/*
+ * per-algorithm NSID names ...
+ */
+char            *skip_nsid_names[MAX_ALGS] = {
+                                        "none",             /* 0 */
+                                        "IPv4",             /* 1 */
+                                        "Posix/Xopen UID",  /* 2 */
+                                        "IPv6",             /* 3 */
+                                        "MD5 DNS",          /* 4 */
+                                        "MD5 ASN.1 DN",     /* 5 */
+                                        "MD5 U.S. Soc. #",  /* 6 */
+                                        "802.x MAC",        /* 7 */
+                                        "MD5 DH Public Key",/* 8 */
+                                        "MD5 RFC822 Mail",  /* 9 */
+                                        "MD5 Bank Account", /* 10 */
+                                        "MD5 NIS Name",     /* 11 */
+                };
+
+
+/*
+ * per-algorithm Kij alg names ...
+ */
+char            *skip_kij_names[MAX_ALGS] = {
+                                        "none",             /* 0 */
+                                        "DES-CBC",          /* 1 */
+                                        "3DES3-EDE-CBC",    /* 2 */
+                                        "IDEA-CBC",         /* 3 */
+               };
+
+
+/* for padding of ekp */
+
+char            skip_kij_sizes[MAX_ALGS] = {
+                                        0, /* 0 none */
+                                        8, /* 1  des-cbc */
+                                        8, /* 2 3des3-ede-cbc */
+                                        8, /* 3 idea-cbc */
+               };
+
+
+/*
+ * per-algorithm Crypt alg names ...
+ */
+char            *skip_crypt_names[MAX_ALGS] = {
+                                        "none",                      /* 0 */
+                                        "DES-CBC",                   /* 1 */
+                                        "3 key DES-EDE-CBC",         /* 2 */
+                                        "",                          /* 3 */
+                                        "",                          /* 4 */
+                                        "",                          /* 5 */
+                                        "",                          /* 6 */
+                                        "",                          /* 7 */
+                                        "",                          /* 8 */
+                                       "",   /* 9 */        /* 10 .. 249 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                                       "RC4-40",                    /* 250 */ 
+                                       "RC4-128",                   /* 251 */
+                                       "simple crypt",              /* 252 */ 
+                                       "IDEA CBC",                  /* 253 */
+                                       "",                          /* 254 */ 
+                                       ""                           /* 255 */
+                };
+
+
+/*
+ * per-algorithm Auth alg names ...
+ */
+char            *skip_auth_names[MAX_ALGS] = {
+                                        "none",        /* 0 */
+                                        "keyed MD5",   /* 1 */
+                                        "DES-CBC MAC", /* 2 */
+                                        "Keyed SHA",   /* 3 */
+                };
+
+
+char            skip_auth_sizes[MAX_ALGS] = {
+                                        0,             /* 0 none */
+                                       16,             /* 1 keyed MD5 */
+                                        8,             /* 2 DES-CBC MAC */
+                                       20,             /* 3 Keyed SHA */
+                };
+
+
+/*
+ * per-algorithm Crypt alg IV sizes ...
+ */
+char            skip_crypt_sizes[MAX_ALGS] = {
+                                        0, /* 0 none */
+                                        8, /* 1 DES-CBC */
+                                        8, /* 2 3key DES-EDE-CBC */
+                                        0, /* 3 */
+                                        0, /* 4 */
+                                        0, /* 5 */
+                                        0, /* 6 */
+                                        0, /* 7 */
+                                        0, /* 8 */
+                                       0, /* 9 */        /* 10 .. 249 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                                       8, /* 250 RC4-40 */ 
+                                       8, /* 251 RC4-128 */
+                                       8, /* 252 simple crypt */ 
+                                       8, /* 253 IDEA CBC */
+                                       0, /* 254 */ 
+                                       0  /* 255 */
+                };
+
+
+#ifndef IPPROTO_ESP
+#define IPPROTO_ESP 50
+#endif
+#ifndef IPPROTO_AH
+#define IPPROTO_AH 51
+#endif
+#ifndef IPPROTO_SKIP
+#define IPPROTO_SKIP 57
+#endif
+#ifndef IPPROTO_OSKIP
+#define IPPROTO_OSKIP 79
+#endif
+
+static int expected_auth_size=0;
+static int expected_iv_size=0;
+
+char *skip_protocol_name(int p)
+{
+    switch(p) {
+       case IPPROTO_IP:    return "IP";
+       case IPPROTO_ICMP:  return "ICMP";
+       case IPPROTO_IGMP:  return "IGMP";
+       case IPPROTO_ENCAP: return "ENCAP";
+       case IPPROTO_TCP:   return "TCP";
+       case IPPROTO_EGP:   return "EGP";
+       case IPPROTO_UDP:   return "UDP";
+       case IPPROTO_ESP:   return "ESP";
+       case IPPROTO_AH:    return "AH";
+       case IPPROTO_SKIP:  return "SKIP";
+       case IPPROTO_ND:    return "ND";
+       case IPPROTO_OSKIP: return "OLD-SKIP";
+       case IPPROTO_RAW:   return "RAW IP";
+       default:            return "<unknown>";
+    }
+}
+
+void skip_print_next(u_char nxt, const u_char *p, int len, const u_char *bp2)
+{
+    switch(nxt) {
+       case IPPROTO_IP:   ip_print(p,len); break;
+       case IPPROTO_ICMP: icmp_print(p,bp2); break;
+       case IPPROTO_TCP:  tcp_print(p,len,bp2); break;
+       case IPPROTO_UDP:  udp_print(p,len,bp2); break;
+       case IPPROTO_ESP:  esp_print(p,len,bp2); break;
+       case IPPROTO_AH:   ah_print(p,len,bp2); break;
+       case IPPROTO_SKIP: skip_print(p,len,bp2); break;
+       default: break;
+    }
+}
+
+void skip_print(register const u_char *bp, register int length, 
+                                                       const u_char *bp2)
+{
+       struct ip *ip;
+       const u_char *end;
+       const u_char *p;
+       unsigned char   kij_alg, crypt_alg, auth_alg, snsid, dnsid, nxt;
+       unsigned short i;
+       unsigned short len;
+       u_int n;
+       time_t full_n;
+
+       ip=(struct ip *)bp2;
+       p=bp;
+       end=bp+length<snapend?bp+length:snapend;
+
+       printf("%s>%s:%d SKIP",ipaddr_string(&ip->ip_src),
+                              ipaddr_string(&ip->ip_dst),length);
+       if (!skipflag)
+               return;
+
+
+        if ((unsigned short) (end - p) < 4) {
+           printf("[SKIP|] (truncated)\n");
+           return;
+        }
+
+       printf("\nSKIP: version\t\t\t%d\n", (int) (*p & 0xf0) >> 4);
+       if (*p & 0xf) 
+               printf("SKIP: version byte \t\treserved,\tis now 0x%x\n", 
+                                                       (int) (*p & 0xf));
+        p++;
+
+        snsid = *p;
+        printf("SKIP: Source NSID\t\t0x%02x\t\t%s\n",
+                   snsid, skip_alg_to_name(skip_nsid_names,snsid));
+        p++;
+
+        dnsid = *p;
+        printf("SKIP: Destination NSID\t\t0x%02x\t\t%s\n",
+                   dnsid, skip_alg_to_name(skip_nsid_names,dnsid));
+        p++;
+
+        nxt = *p;
+        printf("SKIP: Next Protocol Field\t0x%02x\t\t%s\n", nxt, 
+                                                   skip_protocol_name(nxt));
+        p++;
+
+        if ((unsigned short) (end - p) < 4) {
+           printf("[SKIP|] (truncated)\n");
+           return;
+        }
+
+       n=*p++<<24; 
+       n+=*p++<<16;
+       n+=*p++<<8;
+       n+=*p;
+       full_n=(((365*25+6)*24)+n)*3600;
+        printf("SKIP: Counter n Field\t\t0x%08x\t%s", n, 
+                                               asctime(gmtime(&full_n)));
+        p++;
+
+        if ((unsigned short) (end - p) < 4) {
+           printf("[SKIP|] (truncated)\n");
+           return;
+        }
+
+        kij_alg = *p;
+        printf("SKIP: Kij alg (key encryption)\t0x%02x\t\t%s\n",
+                   kij_alg, skip_alg_to_name(skip_kij_names,kij_alg));
+        p++;
+        crypt_alg = *p;
+       expected_iv_size=skip_crypt_sizes[crypt_alg];
+        printf("SKIP: Crypt Alg\t\t\t0x%02x\t\t%s\n",
+                   crypt_alg, skip_alg_to_name(skip_crypt_names,crypt_alg));
+        p++;
+        auth_alg = *p;
+       expected_auth_size=skip_auth_sizes[auth_alg];
+        printf("SKIP: Auth Alg\t\t\t0x%02x\t\t%s\n",
+                   auth_alg, skip_alg_to_name(skip_auth_names,auth_alg));
+        p++;
+        if (*p) printf("SKIP: compression\t\treserved,\tis now0x%02x\n",
+                                                               (int) *p++);
+        else p++;
+
+        /*
+         * encrypted kp (ekp) field
+         */
+
+       if (kij_alg==0 && (crypt_alg || auth_alg)) {
+           printf("Warning: Kij Alg. undefined, but Auth. or Crypt. used!");
+           printf("Warning: Assuming empty Kp\n");
+           crypt_alg=auth_alg=0;
+       }
+        /*
+         * do this with a for-loop to avoid alignment problems and the
+         * overhead of calling bcopy()
+         */
+        len = skip_ekp_sizes[crypt_alg];
+        len = len>(int)skip_auth_sizes[auth_alg]?len:skip_auth_sizes[auth_alg];
+        if (len && skip_kij_sizes[kij_alg] && len % skip_kij_sizes[kij_alg]) {
+           len += skip_kij_sizes[kij_alg] - (len%skip_kij_sizes[kij_alg]);
+       }
+        if ((unsigned short) (end - p) < len) {
+           printf("[SKIP|] (truncated)\n");
+           return;
+        }
+
+        printf("SKIP: Encrypted Kp\t\t");
+        for (i = 0; i < len; i++) {
+                printf("%02x ", (unsigned char) *p++);
+        }
+        printf("\n");
+
+
+        if (snsid) {
+        /*
+         * Source Master Key-ID field
+         */
+           if ((end - p) < skip_nsid_sizes[snsid]) {
+               printf("[SKIP|] (truncated)\n");
+               return;
+           }
+           printf("SKIP: Source Master Key-ID\t");
+            if (snsid==1) {
+               printf("%s",ipaddr_string(p));
+               p+=skip_nsid_sizes[snsid];
+           } else {
+               for (i = 0; i < skip_nsid_sizes[snsid]; i++) {
+                   printf("%02x ", (unsigned char) *p++);
+               }
+           }
+           printf("\n");
+        }
+
+        if (dnsid) {
+        /*
+         * Destination Master Key-ID field
+         */
+           if ((end - p) < skip_nsid_sizes[dnsid]) {
+               printf("[SKIP|] (truncated)\n");
+               return;
+           }
+           printf("SKIP: Dest. Master Key-ID\t");
+            if (dnsid==1) {
+               printf("%s",ipaddr_string(p));
+               p+=skip_nsid_sizes[dnsid];
+           } else {
+               for (i = 0; i < skip_nsid_sizes[dnsid]; i++) {
+                   printf("%02x ", (unsigned char) *p++);
+               }
+           }
+           printf("\n");
+        }
+        if (p<end) skip_print_next(nxt,p,end-p,bp2);
+        else printf("(truncated)\n");
+}
+
+
+
+void ah_print(register const u_char *bp, register int length, 
+                                                       const u_char *bp2)
+{
+       struct ip *ip;
+       const u_char *end;
+       const u_char *p;
+       u_char  nxt;
+       int len, i;
+       u_int spi;
+
+       ip=(struct ip *)bp2;
+       p=bp;
+       end=bp+length<snapend?bp+length:snapend;
+
+
+       printf("SKIP-AH: %s>%s:%d",ipaddr_string(&ip->ip_src),
+                              ipaddr_string(&ip->ip_dst),length);
+       if (!skipflag)
+               return;
+
+       if (end-p <4) {
+            printf("[SKIP-AH|]\n");
+           return;
+       }
+
+        nxt = *p;
+        printf("\nSKIP-AH: Next Protocol Field\t0x%02x\t\t%s\n", nxt, 
+                                                   skip_protocol_name(nxt));
+        p++;
+
+       len= 4 * (int) *p;
+       printf("SKIP-AH: length\t\t\t%d\n", len);
+
+        p++;
+
+        if (*p) printf("SKIP-AH: byte 3\t\t\treserved,\tis now0x%02x\n",
+                                                               (int) *p++);
+        else p++;
+        if (*p) printf("SKIP-AH: byte 4\t\t\treserved,\tis now0x%02x\n",
+                                                               (int) *p++);
+        else p++;
+
+       if (end-p <4) {
+            printf("[SKIP-AH|]\n");
+           return;
+       }
+
+       spi=*p++<<24; 
+       spi+=*p++<<16;
+       spi+=*p++<<8;
+       spi+=*p;
+        printf("SKIP-AH: SPI\t\t\t0x%08x\t", spi );
+       if (spi==0) {
+           printf("NO association\n");
+       } else if (spi==1) {
+           printf("SKIP association\n");
+           if (expected_auth_size) {
+               if (expected_auth_size != len) {
+                   printf("Warning: Length does not match SKIP Auth Alg!\n");
+               }
+               expected_auth_size=0;
+           }
+       } else if (spi<256) {
+           printf("UNKNOWN association\n");
+       } else {
+           printf("DYNAMIC association\n");
+        }
+
+        p++;
+
+        /*
+         * authentication data
+         */
+
+        if ((unsigned short) (end - p) < len) {
+           printf("[SKIP-AH|] (truncated)\n");
+           return;
+        }
+
+        printf("SKIP-AH: Authentication Data\t");
+        for (i = 0; i < len; i++) {
+                printf("%02x ", (unsigned char) *p++);
+               if (i<len-1 && (i+1)%16==0) printf("\n\t\t\t\t");
+        }
+        printf("\n");
+
+        if (p<end) skip_print_next(nxt,p,end-p,bp2);
+        else printf("(truncated)\n");
+}
+
+
+void esp_print(register const u_char *bp, register int length, 
+                                                       const u_char *bp2)
+{
+       struct ip *ip;
+       const u_char *end;
+       const u_char *p;
+       int len, i;
+       u_int spi;
+
+       ip=(struct ip *)bp2;
+       p=bp;
+       end=bp+length<snapend?bp+length:snapend;
+
+
+       printf("SKIP-ESP: %s>%s:%d",ipaddr_string(&ip->ip_src),
+                              ipaddr_string(&ip->ip_dst),length);
+       if (!skipflag)
+               return;
+
+       if (end-p <4) {
+            printf("[SKIP-ESP|]\n");
+       }
+
+       spi=*p++<<24; 
+       spi+=*p++<<16;
+       spi+=*p++<<8;
+       spi+=*p;
+        printf("\nSKIP-ESP: SPI\t\t\t0x%08x\t", spi );
+       if (spi==0) {
+           printf("NO association\n");
+           len=0;
+       } else if (spi==1) {
+           printf("SKIP association\n");
+           len=expected_iv_size;
+           if (!expected_iv_size) {
+               printf("Warning: IV size not defined by SKIP Crypt Alg!\n");
+           } else expected_iv_size=0;
+       } else if (spi<256) {
+           printf("UNKNOWN association\n");
+           len=0;
+       } else {
+           printf("DYNAMIC association\n");
+           len=0;
+        }
+
+        p++;
+        /*
+         * IV data
+         */
+
+        if ((unsigned short) (end - p) < len) {
+           printf("[SKIP-ESP|] (truncated)\n");
+           return;
+        }
+
+        printf("SKIP-ESP: Initalization Vector\t");
+       if (len) {
+           for (i = 0; i < len; i++) {
+                   printf("%02x ", (unsigned char) *p++);
+                   if (i<len-1 && (i+1)%16==0) printf("\n\t\t\t\t");
+           }
+        } else {
+           printf("UNDEFINED (unknown algorithm)");
+       }
+       printf("\n");
+
+       /* no further analysis is possible without decrypting */
+}
+
diff --git a/tcpdump.tproj/print-sl.c b/tcpdump.tproj/print-sl.c
new file mode 100644 (file)
index 0000000..4e4e25e
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-sl.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_NET_SLIP_H
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <net/slcompress.h>
+#include <net/slip.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <pcap.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"                   /* must come after interface.h */
+
+static u_int lastlen[2][256];
+static u_int lastconn = 255;
+
+static void sliplink_print(const u_char *, const struct ip *, u_int);
+static void compressed_sl_print(const u_char *, const struct ip *, u_int, int);
+
+/* XXX BSD/OS 2.1 compatibility */
+#if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR)
+#define SLIP_HDRLEN SLC_BPFHDR
+#define SLX_DIR 0
+#define SLX_CHDR (SLC_BPFHDRLEN - 1)
+#define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN)
+#endif
+
+void
+sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       register u_int caplen = h->caplen;
+       register u_int length = h->len;
+       register const struct ip *ip;
+
+       ts_print(&h->ts);
+
+       if (caplen < SLIP_HDRLEN) {
+               printf("[|slip]");
+               goto out;
+       }
+       /*
+        * Some printers want to get back at the link level addresses,
+        * and/or check that they're not walking off the end of the packet.
+        * Rather than pass them all the way down, we set these globals.
+        */
+       packetp = p;
+       snapend = p + caplen;
+
+       length -= SLIP_HDRLEN;
+
+       ip = (struct ip *)(p + SLIP_HDRLEN);
+
+       if (eflag)
+               sliplink_print(p, ip, length);
+
+       ip_print((u_char *)ip, length);
+
+       if (xflag)
+               default_print((u_char *)ip, caplen - SLIP_HDRLEN);
+ out:
+       putchar('\n');
+}
+
+static void
+sliplink_print(register const u_char *p, register const struct ip *ip,
+              register u_int length)
+{
+       int dir;
+       u_int hlen;
+
+       dir = p[SLX_DIR];
+       putchar(dir == SLIPDIR_IN ? 'I' : 'O');
+       putchar(' ');
+
+       if (nflag) {
+               /* XXX just dump the header */
+               register int i;
+
+               for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
+                       printf("%02x.", p[i]);
+               printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]);
+               return;
+       }
+       switch (p[SLX_CHDR] & 0xf0) {
+
+       case TYPE_IP:
+               printf("ip %d: ", length + SLIP_HDRLEN);
+               break;
+
+       case TYPE_UNCOMPRESSED_TCP:
+               /*
+                * The connection id is stored in the IP protocol field.
+                * Get it from the link layer since sl_uncompress_tcp()
+                * has restored the IP header copy to IPPROTO_TCP.
+                */
+               lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
+               hlen = ip->ip_hl;
+               hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off;
+               lastlen[dir][lastconn] = length - (hlen << 2);
+               printf("utcp %d: ", lastconn);
+               break;
+
+       default:
+               if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
+                       compressed_sl_print(&p[SLX_CHDR], ip,
+                           length, dir);
+                       printf(": ");
+               } else
+                       printf("slip-%d!: ", p[SLX_CHDR]);
+       }
+}
+
+static const u_char *
+print_sl_change(const char *str, register const u_char *cp)
+{
+       register u_int i;
+
+       if ((i = *cp++) == 0) {
+               i = EXTRACT_16BITS(cp);
+               cp += 2;
+       }
+       printf(" %s%d", str, i);
+       return (cp);
+}
+
+static const u_char *
+print_sl_winchange(register const u_char *cp)
+{
+       register short i;
+
+       if ((i = *cp++) == 0) {
+               i = EXTRACT_16BITS(cp);
+               cp += 2;
+       }
+       if (i >= 0)
+               printf(" W+%d", i);
+       else
+               printf(" W%d", i);
+       return (cp);
+}
+
+static void
+compressed_sl_print(const u_char *chdr, const struct ip *ip,
+                   u_int length, int dir)
+{
+       register const u_char *cp = chdr;
+       register u_int flags, hlen;
+
+       flags = *cp++;
+       if (flags & NEW_C) {
+               lastconn = *cp++;
+               printf("ctcp %d", lastconn);
+       } else
+               printf("ctcp *");
+
+       /* skip tcp checksum */
+       cp += 2;
+
+       switch (flags & SPECIALS_MASK) {
+       case SPECIAL_I:
+               printf(" *SA+%d", lastlen[dir][lastconn]);
+               break;
+
+       case SPECIAL_D:
+               printf(" *S+%d", lastlen[dir][lastconn]);
+               break;
+
+       default:
+               if (flags & NEW_U)
+                       cp = print_sl_change("U=", cp);
+               if (flags & NEW_W)
+                       cp = print_sl_winchange(cp);
+               if (flags & NEW_A)
+                       cp = print_sl_change("A+", cp);
+               if (flags & NEW_S)
+                       cp = print_sl_change("S+", cp);
+               break;
+       }
+       if (flags & NEW_I)
+               cp = print_sl_change("I+", cp);
+
+       /*
+        * 'hlen' is the length of the uncompressed TCP/IP header (in words).
+        * 'cp - chdr' is the length of the compressed header.
+        * 'length - hlen' is the amount of data in the packet.
+        */
+       hlen = ip->ip_hl;
+       hlen += ((struct tcphdr *)&((int32_t *)ip)[hlen])->th_off;
+       lastlen[dir][lastconn] = length - (hlen << 2);
+       printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr);
+}
+#else
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <pcap.h>
+#include <stdio.h>
+
+#include "interface.h"
+void
+sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+
+       error("not configured for slip");
+       /* NOTREACHED */
+}
+#endif
diff --git a/tcpdump.tproj/print-snmp.c b/tcpdump.tproj/print-snmp.c
new file mode 100644 (file)
index 0000000..860be8a
--- /dev/null
@@ -0,0 +1,1063 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by John Robert LoVerso.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This implementation has been influenced by the CMU SNMP release,
+ * by Steve Waldbusser.  However, this shares no code with that system.
+ * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
+ * Earlier forms of this implementation were derived and/or inspired by an
+ * awk script originally written by C. Philip Wood of LANL (but later
+ * heavily modified by John Robert LoVerso).  The copyright notice for
+ * that work is preserved below, even though it may not rightly apply
+ * to this file.
+ *
+ * This started out as a very simple program, but the incremental decoding
+ * (into the BE structure) complicated things.
+ *
+ #                     Los Alamos National Laboratory
+ #
+ #     Copyright, 1990.  The Regents of the University of California.
+ #     This software was produced under a U.S. Government contract
+ #     (W-7405-ENG-36) by Los Alamos National Laboratory, which is
+ #     operated by the University of California for the U.S. Department
+ #     of Energy.  The U.S. Government is licensed to use, reproduce,
+ #     and distribute this software.  Permission is granted to the
+ #     public to copy and use this software without charge, provided
+ #     that this Notice and any statement of authorship are reproduced
+ #     on all copies.  Neither the Government nor the University makes
+ #     any warranty, express or implied, or assumes any liability or
+ #     responsibility for the use of this software.
+ #     @(#)snmp.awk.x  1.1 (LANL) 1/15/90
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-snmp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/*
+ * Universal ASN.1 types
+ * (we only care about the tag values for those allowed in the Internet SMI)
+ */
+char *Universal[] = {
+       "U-0",
+       "Boolean",
+       "Integer",
+#define INTEGER 2
+       "Bitstring",
+       "String",
+#define STRING 4
+       "Null",
+#define ASN_NULL 5
+       "ObjID",
+#define OBJECTID 6
+       "ObjectDes",
+       "U-8","U-9","U-10","U-11",      /* 8-11 */
+       "U-12","U-13","U-14","U-15",    /* 12-15 */
+       "Sequence",
+#define SEQUENCE 16
+       "Set"
+};
+
+/*
+ * Application-wide ASN.1 types from the Internet SMI and their tags
+ */
+char *Application[] = {
+       "IpAddress",
+#define IPADDR 0
+       "Counter",
+#define COUNTER 1
+       "Gauge",
+#define GAUGE 2
+       "TimeTicks",
+#define TIMETICKS 3
+       "Opaque"
+};
+
+/*
+ * Context-specific ASN.1 types for the SNMP PDUs and their tags
+ */
+char *Context[] = {
+       "GetRequest",
+#define GETREQ 0
+       "GetNextRequest",
+#define GETNEXTREQ 1
+       "GetResponse",
+#define GETRESP 2
+       "SetRequest",
+#define SETREQ 3
+       "Trap"
+#define TRAP 4
+};
+
+/*
+ * Private ASN.1 types
+ * The Internet SMI does not specify any
+ */
+char *Private[] = {
+       "P-0"
+};
+
+/*
+ * error-status values for any SNMP PDU
+ */
+char *ErrorStatus[] = {
+       "noError",
+       "tooBig",
+       "noSuchName",
+       "badValue",
+       "readOnly",
+       "genErr"
+};
+#define DECODE_ErrorStatus(e) \
+       ( e >= 0 && e <= sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
+       ? ErrorStatus[e] : (sprintf(errbuf, "err=%u", e), errbuf))
+
+/*
+ * generic-trap values in the SNMP Trap-PDU
+ */
+char *GenericTrap[] = {
+       "coldStart",
+       "warmStart",
+       "linkDown",
+       "linkUp",
+       "authenticationFailure",
+       "egpNeighborLoss",
+       "enterpriseSpecific"
+#define GT_ENTERPRISE 7
+};
+#define DECODE_GenericTrap(t) \
+       ( t >= 0 && t <= sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
+       ? GenericTrap[t] : (sprintf(buf, "gt=%d", t), buf))
+
+/*
+ * ASN.1 type class table
+ * Ties together the preceding Universal, Application, Context, and Private
+ * type definitions.
+ */
+#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
+struct {
+       char    *name;
+       char    **Id;
+           int numIDs;
+    } Class[] = {
+       defineCLASS(Universal),
+#define        UNIVERSAL       0
+       defineCLASS(Application),
+#define        APPLICATION     1
+       defineCLASS(Context),
+#define        CONTEXT         2
+       defineCLASS(Private),
+#define        PRIVATE         3
+};
+
+/*
+ * defined forms for ASN.1 types
+ */
+char *Form[] = {
+       "Primitive",
+#define PRIMITIVE      0
+       "Constructed",
+#define CONSTRUCTED    1
+};
+
+/*
+ * A structure for the OID tree for the compiled-in MIB.
+ * This is stored as a general-order tree.
+ */
+struct obj {
+       char    *desc;                  /* name of object */
+       u_char  oid;                    /* sub-id following parent */
+       u_char  type;                   /* object type (unused) */
+       struct obj *child, *next;       /* child and next sibling pointers */
+} *objp = NULL;
+
+/*
+ * Include the compiled in SNMP MIB.  "mib.h" is produced by feeding
+ * RFC-1156 format files into "makemib".  "mib.h" MUST define at least
+ * a value for `mibroot'.
+ *
+ * In particular, this is gross, as this is including initialized structures,
+ * and by right shouldn't be an "include" file.
+ */
+#include "mib.h"
+
+/*
+ * This defines a list of OIDs which will be abbreviated on output.
+ * Currently, this includes the prefixes for the Internet MIB, the
+ * private enterprises tree, and the experimental tree.
+ */
+struct obj_abrev {
+       char *prefix;                   /* prefix for this abrev */
+       struct obj *node;               /* pointer into object table */
+       char *oid;                      /* ASN.1 encoded OID */
+} obj_abrev_list[] = {
+#ifndef NO_ABREV_MIB
+       /* .iso.org.dod.internet.mgmt.mib */
+       { "",   &_mib_obj,              "\53\6\1\2\1" },
+#endif
+#ifndef NO_ABREV_ENTER
+       /* .iso.org.dod.internet.private.enterprises */
+       { "E:", &_enterprises_obj,      "\53\6\1\4\1" },
+#endif
+#ifndef NO_ABREV_EXPERI
+       /* .iso.org.dod.internet.experimental */
+       { "X:", &_experimental_obj,     "\53\6\1\3" },
+#endif
+       { 0,0,0 }
+};
+
+/*
+ * This is used in the OID print routine to walk down the object tree
+ * rooted at `mibroot'.
+ */
+#define OBJ_PRINT(o, suppressdot) \
+{ \
+       if (objp) { \
+               do { \
+                       if ((o) == objp->oid) \
+                               break; \
+               } while ((objp = objp->next) != NULL); \
+       } \
+       if (objp) { \
+               printf(suppressdot?"%s":".%s", objp->desc); \
+               objp = objp->child; \
+       } else \
+               printf(suppressdot?"%u":".%u", (o)); \
+}
+
+/*
+ * This is the definition for the Any-Data-Type storage used purely for
+ * temporary internal representation while decoding an ASN.1 data stream.
+ */
+struct be {
+       u_int32_t asnlen;
+       union {
+               caddr_t raw;
+               int32_t integer;
+               u_int32_t uns;
+               const u_char *str;
+       } data;
+       u_short id;
+       u_char form, class;             /* tag info */
+       u_char type;
+#define BE_ANY         255
+#define BE_NONE                0
+#define BE_NULL                1
+#define BE_OCTET       2
+#define BE_OID         3
+#define BE_INT         4
+#define BE_UNS         5
+#define BE_STR         6
+#define BE_SEQ         7
+#define BE_INETADDR    8
+#define BE_PDU         9
+};
+
+/*
+ * Defaults for SNMP PDU components
+ */
+#define DEF_COMMUNITY "public"
+#define DEF_VERSION 0
+
+/*
+ * constants for ASN.1 decoding
+ */
+#define OIDMUX 40
+#define ASNLEN_INETADDR 4
+#define ASN_SHIFT7 7
+#define ASN_SHIFT8 8
+#define ASN_BIT8 0x80
+#define ASN_LONGLEN 0x80
+
+#define ASN_ID_BITS 0x1f
+#define ASN_FORM_BITS 0x20
+#define ASN_FORM_SHIFT 5
+#define ASN_CLASS_BITS 0xc0
+#define ASN_CLASS_SHIFT 6
+
+#define ASN_ID_EXT 0x1f                /* extension ID in tag field */
+
+/*
+ * truncated==1 means the packet was complete, but we don't have all of
+ * it to decode.
+ */
+static int truncated;
+#define ifNotTruncated if (truncated) fputs("[|snmp]", stdout); else
+
+/*
+ * This decodes the next ASN.1 object in the stream pointed to by "p"
+ * (and of real-length "len") and stores the intermediate data in the
+ * provided BE object.
+ *
+ * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
+ * O/w, this returns the number of bytes parsed from "p".
+ */
+static int
+asn1_parse(register const u_char *p, u_int len, struct be *elem)
+{
+       u_char form, class, id;
+       int i, hdr;
+
+       elem->asnlen = 0;
+       elem->type = BE_ANY;
+       if (len < 1) {
+               ifNotTruncated puts("[nothing to parse], stdout");
+               return -1;
+       }
+
+       /*
+        * it would be nice to use a bit field, but you can't depend on them.
+        *  +---+---+---+---+---+---+---+---+
+        *  + class |frm|        id         |
+        *  +---+---+---+---+---+---+---+---+
+        *    7   6   5   4   3   2   1   0
+        */
+       id = *p & ASN_ID_BITS;          /* lower 5 bits, range 00-1f */
+#ifdef notdef
+       form = (*p & 0xe0) >> 5;        /* move upper 3 bits to lower 3 */
+       class = form >> 1;              /* bits 7&6 -> bits 1&0, range 0-3 */
+       form &= 0x1;                    /* bit 5 -> bit 0, range 0-1 */
+#else
+       form = (u_char)(*p & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
+       class = (u_char)(*p & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
+#endif
+       elem->form = form;
+       elem->class = class;
+       elem->id = id;
+       if (vflag)
+               printf("|%.2x", *p);
+       p++; len--; hdr = 1;
+       /* extended tag field */
+       if (id == ASN_ID_EXT) {
+               for (id = 0; *p & ASN_BIT8 && len > 0; len--, hdr++, p++) {
+                       if (vflag)
+                               printf("|%.2x", *p);
+                       id = (id << 7) | (*p & ~ASN_BIT8);
+               }
+               if (len == 0 && *p & ASN_BIT8) {
+                       ifNotTruncated fputs("[Xtagfield?]", stdout);
+                       return -1;
+               }
+               elem->id = id = (id << 7) | *p;
+               --len;
+               ++hdr;
+               ++p;
+       }
+       if (len < 1) {
+               ifNotTruncated fputs("[no asnlen]", stdout);
+               return -1;
+       }
+       elem->asnlen = *p;
+       if (vflag)
+               printf("|%.2x", *p);
+       p++; len--; hdr++;
+       if (elem->asnlen & ASN_BIT8) {
+               int noct = elem->asnlen % ASN_BIT8;
+               elem->asnlen = 0;
+               if (len < noct) {
+                       ifNotTruncated printf("[asnlen? %d<%d]", len, noct);
+                       return -1;
+               }
+               for (; noct-- > 0; len--, hdr++) {
+                       if (vflag)
+                               printf("|%.2x", *p);
+                       elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++;
+               }
+       }
+       if (len < elem->asnlen) {
+               if (!truncated) {
+                       printf("[len%d<asnlen%u]", len, elem->asnlen);
+                       return -1;
+               }
+               /* maybe should check at least 4? */
+               elem->asnlen = len;
+       }
+       if (form >= sizeof(Form)/sizeof(Form[0])) {
+               ifNotTruncated printf("[form?%d]", form);
+               return -1;
+       }
+       if (class >= sizeof(Class)/sizeof(Class[0])) {
+               ifNotTruncated printf("[class?%c/%d]", *Form[form], class);
+               return -1;
+       }
+       if ((int)id >= Class[class].numIDs) {
+               ifNotTruncated printf("[id?%c/%s/%d]", *Form[form],
+                       Class[class].name, id);
+               return -1;
+       }
+
+       switch (form) {
+       case PRIMITIVE:
+               switch (class) {
+               case UNIVERSAL:
+                       switch (id) {
+                       case STRING:
+                               elem->type = BE_STR;
+                               elem->data.str = p;
+                               break;
+
+                       case INTEGER: {
+                               register int32_t data;
+                               elem->type = BE_INT;
+                               data = 0;
+
+                               if (*p & ASN_BIT8)      /* negative */
+                                       data = -1;
+                               for (i = elem->asnlen; i-- > 0; p++)
+                                       data = (data << ASN_SHIFT8) | *p;
+                               elem->data.integer = data;
+                               break;
+                       }
+
+                       case OBJECTID:
+                               elem->type = BE_OID;
+                               elem->data.raw = (caddr_t)p;
+                               break;
+
+                       case ASN_NULL:
+                               elem->type = BE_NULL;
+                               elem->data.raw = NULL;
+                               break;
+
+                       default:
+                               elem->type = BE_OCTET;
+                               elem->data.raw = (caddr_t)p;
+                               printf("[P/U/%s]",
+                                       Class[class].Id[id]);
+                               break;
+                       }
+                       break;
+
+               case APPLICATION:
+                       switch (id) {
+                       case IPADDR:
+                               elem->type = BE_INETADDR;
+                               elem->data.raw = (caddr_t)p;
+                               break;
+
+                       case COUNTER:
+                       case GAUGE:
+                       case TIMETICKS: {
+                               register u_int32_t data;
+                               elem->type = BE_UNS;
+                               data = 0;
+                               for (i = elem->asnlen; i-- > 0; p++)
+                                       data = (data << 8) + *p;
+                               elem->data.uns = data;
+                               break;
+                       }
+
+                       default:
+                               elem->type = BE_OCTET;
+                               elem->data.raw = (caddr_t)p;
+                               printf("[P/A/%s]",
+                                       Class[class].Id[id]);
+                               break;
+                       }
+                       break;
+
+               default:
+                       elem->type = BE_OCTET;
+                       elem->data.raw = (caddr_t)p;
+                       printf("[P/%s/%s]",
+                               Class[class].name, Class[class].Id[id]);
+                       break;
+               }
+               break;
+
+       case CONSTRUCTED:
+               switch (class) {
+               case UNIVERSAL:
+                       switch (id) {
+                       case SEQUENCE:
+                               elem->type = BE_SEQ;
+                               elem->data.raw = (caddr_t)p;
+                               break;
+
+                       default:
+                               elem->type = BE_OCTET;
+                               elem->data.raw = (caddr_t)p;
+                               printf("C/U/%s", Class[class].Id[id]);
+                               break;
+                       }
+                       break;
+
+               case CONTEXT:
+                       elem->type = BE_PDU;
+                       elem->data.raw = (caddr_t)p;
+                       break;
+
+               default:
+                       elem->type = BE_OCTET;
+                       elem->data.raw = (caddr_t)p;
+                       printf("C/%s/%s",
+                               Class[class].name, Class[class].Id[id]);
+                       break;
+               }
+               break;
+       }
+       p += elem->asnlen;
+       len -= elem->asnlen;
+       return elem->asnlen + hdr;
+}
+
+/*
+ * Display the ASN.1 object represented by the BE object.
+ * This used to be an integral part of asn1_parse() before the intermediate
+ * BE form was added.
+ */
+static void
+asn1_print(struct be *elem)
+{
+       u_char *p = (u_char *)elem->data.raw;
+       u_int32_t asnlen = elem->asnlen;
+       int i;
+
+       switch (elem->type) {
+
+       case BE_OCTET:
+               for (i = asnlen; i-- > 0; p++);
+                       printf("_%.2x", *p);
+               break;
+
+       case BE_NULL:
+               break;
+
+       case BE_OID: {
+       int o = 0, first = -1, i = asnlen;
+
+               if (!nflag && asnlen > 2) {
+                       struct obj_abrev *a = &obj_abrev_list[0];
+                       for (; a->node; a++) {
+                               if (!memcmp(a->oid, (char *)p,
+                                   strlen(a->oid))) {
+                                       objp = a->node->child;
+                                       i -= strlen(a->oid);
+                                       p += strlen(a->oid);
+                                       fputs(a->prefix, stdout);
+                                       first = 1;
+                                       break;
+                               }
+                       }
+               }
+               for (; i-- > 0; p++) {
+                       o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
+                       if (*p & ASN_LONGLEN)
+                               continue;
+
+                       /*
+                        * first subitem encodes two items with 1st*OIDMUX+2nd
+                        */
+                       if (first < 0) {
+                               if (!nflag)
+                                       objp = mibroot;
+                               first = 0;
+                               OBJ_PRINT(o/OIDMUX, first);
+                               o %= OIDMUX;
+                       }
+                       OBJ_PRINT(o, first);
+                       if (--first < 0)
+                               first = 0;
+                       o = 0;
+               }
+               break;
+       }
+
+       case BE_INT:
+               printf("%d", elem->data.integer);
+               break;
+
+       case BE_UNS:
+               printf("%d", elem->data.uns);
+               break;
+
+       case BE_STR: {
+               register int printable = 1, first = 1;
+               const u_char *p = elem->data.str;
+               for (i = asnlen; printable && i-- > 0; p++)
+                       printable = isprint(*p) || isspace(*p);
+               p = elem->data.str;
+               if (printable) {
+                       putchar('"');
+                       (void)fn_print(p, p + asnlen);
+                       putchar('"');
+               } else
+                       for (i = asnlen; i-- > 0; p++) {
+                               printf(first ? "%.2x" : "_%.2x", *p);
+                               first = 0;
+                       }
+               break;
+       }
+
+       case BE_SEQ:
+               printf("Seq(%u)", elem->asnlen);
+               break;
+
+       case BE_INETADDR: {
+               char sep;
+               if (asnlen != ASNLEN_INETADDR)
+                       printf("[inetaddr len!=%d]", ASNLEN_INETADDR);
+               sep='[';
+               for (i = asnlen; i-- > 0; p++) {
+                       printf("%c%u", sep, *p);
+                       sep='.';
+               }
+               putchar(']');
+               break;
+       }
+
+       case BE_PDU:
+               printf("%s(%u)",
+                       Class[CONTEXT].Id[elem->id], elem->asnlen);
+               break;
+
+       case BE_ANY:
+               fputs("[BE_ANY!?]", stdout);
+               break;
+
+       default:
+               fputs("[be!?]", stdout);
+               break;
+       }
+}
+
+#ifdef notdef
+/*
+ * This is a brute force ASN.1 printer: recurses to dump an entire structure.
+ * This will work for any ASN.1 stream, not just an SNMP PDU.
+ *
+ * By adding newlines and spaces at the correct places, this would print in
+ * Rose-Normal-Form.
+ *
+ * This is not currently used.
+ */
+static void
+asn1_decode(u_char *p, u_int length)
+{
+       struct be elem;
+       int i = 0;
+
+       while (i >= 0 && length > 0) {
+               i = asn1_parse(p, length, &elem);
+               if (i >= 0) {
+                       fputs(" ", stdout);
+                       asn1_print(&elem);
+                       if (elem.type == BE_SEQ || elem.type == BE_PDU) {
+                               fputs(" {", stdout);
+                               asn1_decode(elem.data.raw, elem.asnlen);
+                               fputs(" }", stdout);
+                       }
+                       length -= i;
+                       p += i;
+               }
+       }
+}
+#endif
+
+/*
+ * General SNMP header
+ *     SEQUENCE {
+ *             version INTEGER {version-1(0)},
+ *             community OCTET STRING,
+ *             data ANY        -- PDUs
+ *     }
+ * PDUs for all but Trap: (see rfc1157 from page 15 on)
+ *     SEQUENCE {
+ *             request-id INTEGER,
+ *             error-status INTEGER,
+ *             error-index INTEGER,
+ *             varbindlist SEQUENCE OF
+ *                     SEQUENCE {
+ *                             name ObjectName,
+ *                             value ObjectValue
+ *                     }
+ *     }
+ * PDU for Trap:
+ *     SEQUENCE {
+ *             enterprise OBJECT IDENTIFIER,
+ *             agent-addr NetworkAddress,
+ *             generic-trap INTEGER,
+ *             specific-trap INTEGER,
+ *             time-stamp TimeTicks,
+ *             varbindlist SEQUENCE OF
+ *                     SEQUENCE {
+ *                             name ObjectName,
+ *                             value ObjectValue
+ *                     }
+ *     }
+ */
+
+/*
+ * Decode SNMP varBind
+ */
+static void
+varbind_print(u_char pduid, const u_char *np, u_int length, int error)
+{
+       struct be elem;
+       int count = 0, ind;
+
+       /* Sequence of varBind */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_SEQ) {
+               fputs("[!SEQ of varbind]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       if (count < length)
+               printf("[%d extra after SEQ of varbind]", length - count);
+       /* descend */
+       length = elem.asnlen;
+       np = (u_char *)elem.data.raw;
+
+       for (ind = 1; length > 0; ind++) {
+               const u_char *vbend;
+               u_int vblength;
+
+               if (!error || ind == error)
+                       fputs(" ", stdout);
+
+               /* Sequence */
+               if ((count = asn1_parse(np, length, &elem)) < 0)
+                       return;
+               if (elem.type != BE_SEQ) {
+                       fputs("[!varbind]", stdout);
+                       asn1_print(&elem);
+                       return;
+               }
+               vbend = np + count;
+               vblength = length - count;
+               /* descend */
+               length = elem.asnlen;
+               np = (u_char *)elem.data.raw;
+
+               /* objName (OID) */
+               if ((count = asn1_parse(np, length, &elem)) < 0)
+                       return;
+               if (elem.type != BE_OID) {
+                       fputs("[objName!=OID]", stdout);
+                       asn1_print(&elem);
+                       return;
+               }
+               if (!error || ind == error)
+                       asn1_print(&elem);
+               length -= count;
+               np += count;
+
+               if (pduid != GETREQ && pduid != GETNEXTREQ && !error)
+                               fputs("=", stdout);
+
+               /* objVal (ANY) */
+               if ((count = asn1_parse(np, length, &elem)) < 0)
+                       return;
+               if (pduid == GETREQ || pduid == GETNEXTREQ) {
+                       if (elem.type != BE_NULL) {
+                               fputs("[objVal!=NULL]", stdout);
+                               asn1_print(&elem);
+                       }
+               } else
+                       if (error && ind == error && elem.type != BE_NULL)
+                               fputs("[err objVal!=NULL]", stdout);
+                       if (!error || ind == error)
+                               asn1_print(&elem);
+
+               length = vblength;
+               np = vbend;
+       }
+}
+
+/*
+ * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest
+ */
+static void
+snmppdu_print(u_char pduid, const u_char *np, u_int length)
+{
+       struct be elem;
+       int count = 0, error;
+
+       /* reqId (Integer) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_INT) {
+               fputs("[reqId!=INT]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       /* ignore the reqId */
+       length -= count;
+       np += count;
+
+       /* errorStatus (Integer) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_INT) {
+               fputs("[errorStatus!=INT]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       error = 0;
+       if ((pduid == GETREQ || pduid == GETNEXTREQ)
+           && elem.data.integer != 0) {
+               char errbuf[10];
+               printf("[errorStatus(%s)!=0]",
+                       DECODE_ErrorStatus(elem.data.integer));
+       } else if (elem.data.integer != 0) {
+               char errbuf[10];
+               printf(" %s", DECODE_ErrorStatus(elem.data.integer));
+               error = elem.data.integer;
+       }
+       length -= count;
+       np += count;
+
+       /* errorIndex (Integer) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_INT) {
+               fputs("[errorIndex!=INT]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       if ((pduid == GETREQ || pduid == GETNEXTREQ)
+           && elem.data.integer != 0)
+               printf("[errorIndex(%d)!=0]", elem.data.integer);
+       else if (elem.data.integer != 0) {
+               if (!error)
+                       printf("[errorIndex(%d) w/o errorStatus]",
+                               elem.data.integer);
+               else {
+                       printf("@%d", elem.data.integer);
+                       error = elem.data.integer;
+               }
+       } else if (error) {
+               fputs("[errorIndex==0]", stdout);
+               error = 0;
+       }
+       length -= count;
+       np += count;
+
+       varbind_print(pduid, np, length, error);
+       return;
+}
+
+/*
+ * Decode SNMP Trap PDU
+ */
+static void
+trap_print(const u_char *np, u_int length)
+{
+       struct be elem;
+       int count = 0, generic;
+
+       putchar(' ');
+
+       /* enterprise (oid) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_OID) {
+               fputs("[enterprise!=OID]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       asn1_print(&elem);
+       length -= count;
+       np += count;
+
+       putchar(' ');
+
+       /* agent-addr (inetaddr) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_INETADDR) {
+               fputs("[agent-addr!=INETADDR]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       asn1_print(&elem);
+       length -= count;
+       np += count;
+
+       /* generic-trap (Integer) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_INT) {
+               fputs("[generic-trap!=INT]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       generic = elem.data.integer;
+       {
+               char buf[10];
+               printf(" %s", DECODE_GenericTrap(generic));
+       }
+       length -= count;
+       np += count;
+
+       /* specific-trap (Integer) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_INT) {
+               fputs("[specific-trap!=INT]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       if (generic != GT_ENTERPRISE) {
+               if (elem.data.integer != 0)
+                       printf("[specific-trap(%d)!=0]", elem.data.integer);
+       } else
+               printf(" s=%d", elem.data.integer);
+       length -= count;
+       np += count;
+
+       putchar(' ');
+
+       /* time-stamp (TimeTicks) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_UNS) {                      /* XXX */
+               fputs("[time-stamp!=TIMETICKS]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       asn1_print(&elem);
+       length -= count;
+       np += count;
+
+       varbind_print (TRAP, np, length, 0);
+       return;
+}
+
+/*
+ * Decode SNMP header and pass on to PDU printing routines
+ */
+void
+snmp_print(const u_char *np, u_int length)
+{
+       struct be elem, pdu;
+       int count = 0;
+
+       truncated = 0;
+
+       /* truncated packet? */
+       if (np + length > snapend) {
+               truncated = 1;
+               length = snapend - np;
+       }
+
+       putchar(' ');
+
+       /* initial Sequence */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_SEQ) {
+               fputs("[!init SEQ]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       if (count < length)
+               printf("[%d extra after iSEQ]", length - count);
+       /* descend */
+       length = elem.asnlen;
+       np = (u_char *)elem.data.raw;
+       /* Version (Integer) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_INT) {
+               fputs("[version!=INT]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       /* only handle version==0 */
+       if (elem.data.integer != DEF_VERSION) {
+               printf("[version(%d)!=0]", elem.data.integer);
+               return;
+       }
+       length -= count;
+       np += count;
+
+       /* Community (String) */
+       if ((count = asn1_parse(np, length, &elem)) < 0)
+               return;
+       if (elem.type != BE_STR) {
+               fputs("[comm!=STR]", stdout);
+               asn1_print(&elem);
+               return;
+       }
+       /* default community */
+       if (strncmp((char *)elem.data.str, DEF_COMMUNITY,
+           sizeof(DEF_COMMUNITY) - 1))
+               /* ! "public" */
+               printf("C=%.*s ", (int)elem.asnlen, elem.data.str);
+       length -= count;
+       np += count;
+
+       /* PDU (Context) */
+       if ((count = asn1_parse(np, length, &pdu)) < 0)
+               return;
+       if (pdu.type != BE_PDU) {
+               fputs("[no PDU]", stdout);
+               return;
+       }
+       if (count < length)
+               printf("[%d extra after PDU]", length - count);
+       asn1_print(&pdu);
+       /* descend into PDU */
+       length = pdu.asnlen;
+       np = (u_char *)pdu.data.raw;
+
+       switch (pdu.id) {
+       case TRAP:
+               trap_print(np, length);
+               break;
+       case GETREQ:
+       case GETNEXTREQ:
+       case GETRESP:
+       case SETREQ:
+               snmppdu_print(pdu.id, np, length);
+               break;
+       }
+       return;
+}
diff --git a/tcpdump.tproj/print-sunrpc.c b/tcpdump.tproj/print-sunrpc.c
new file mode 100644 (file)
index 0000000..0c9f696
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-sunrpc.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <rpc/rpc.h>
+#ifdef HAVE_RPC_RPCENT_H
+#include <rpc/rpcent.h>
+#endif
+#include <rpc/pmap_prot.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+static struct tok proc2str[] = {
+       { PMAPPROC_NULL,        "null" },
+       { PMAPPROC_SET,         "set" },
+       { PMAPPROC_UNSET,       "unset" },
+       { PMAPPROC_GETPORT,     "getport" },
+       { PMAPPROC_DUMP,        "dump" },
+       { PMAPPROC_CALLIT,      "call" },
+       { 0,                    NULL }
+};
+
+/* Forwards */
+static char *progstr(u_int32_t);
+
+void
+sunrpcrequest_print(register const u_char *bp, register u_int length,
+                   register const u_char *bp2)
+{
+       register const struct rpc_msg *rp;
+       register const struct ip *ip;
+       u_int32_t x;
+
+       rp = (struct rpc_msg *)bp;
+       ip = (struct ip *)bp2;
+
+       if (!nflag)
+               (void)printf("%s.%x > %s.sunrpc: %d",
+                            ipaddr_string(&ip->ip_src),
+                            (u_int32_t)ntohl(rp->rm_xid),
+                            ipaddr_string(&ip->ip_dst),
+                            length);
+       else
+               (void)printf("%s.%x > %s.%x: %d",
+                            ipaddr_string(&ip->ip_src),
+                            (u_int32_t)ntohl(rp->rm_xid),
+                            ipaddr_string(&ip->ip_dst),
+                            PMAPPORT,
+                            length);
+       printf(" %s", tok2str(proc2str, " proc #%u",
+           (u_int32_t)ntohl(rp->rm_call.cb_proc)));
+       x = ntohl(rp->rm_call.cb_rpcvers);
+       if (x != 2)
+               printf(" [rpcver %u]", x);
+
+       switch (ntohl(rp->rm_call.cb_proc)) {
+
+       case PMAPPROC_SET:
+       case PMAPPROC_UNSET:
+       case PMAPPROC_GETPORT:
+       case PMAPPROC_CALLIT:
+               x = ntohl(rp->rm_call.cb_prog);
+               if (!nflag)
+                       printf(" %s", progstr(x));
+               else
+                       printf(" %u", x);
+               printf(".%u", (u_int32_t)ntohl(rp->rm_call.cb_vers));
+               break;
+       }
+}
+
+static char *
+progstr(prog)
+       u_int32_t prog;
+{
+       register struct rpcent *rp;
+       static char buf[32];
+       static lastprog = 0;
+
+       if (lastprog != 0 && prog == lastprog)
+               return (buf);
+       rp = getrpcbynumber(prog);
+       if (rp == NULL)
+               (void) sprintf(buf, "#%u", prog);
+       else
+               strcpy(buf, rp->r_name);
+       return (buf);
+}
diff --git a/tcpdump.tproj/print-tcp.c b/tcpdump.tproj/print-tcp.c
new file mode 100644 (file)
index 0000000..2c0d1e3
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-tcp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"
+
+/* Compatibility */
+#ifndef TCPOPT_WSCALE
+#define        TCPOPT_WSCALE           3       /* window scale factor (rfc1072) */
+#endif
+#ifndef TCPOPT_SACKOK
+#define        TCPOPT_SACKOK           4       /* selective ack ok (rfc1072) */
+#endif
+#ifndef TCPOPT_SACK
+#define        TCPOPT_SACK             5       /* selective ack (rfc1072) */
+#endif
+#ifndef TCPOPT_ECHO
+#define        TCPOPT_ECHO             6       /* echo (rfc1072) */
+#endif
+#ifndef TCPOPT_ECHOREPLY
+#define        TCPOPT_ECHOREPLY        7       /* echo (rfc1072) */
+#endif
+#ifndef TCPOPT_TIMESTAMP
+#define TCPOPT_TIMESTAMP       8       /* timestamps (rfc1323) */
+#endif
+#ifndef TCPOPT_CC
+#define TCPOPT_CC              11      /* T/TCP CC options (rfc1644) */
+#endif
+#ifndef TCPOPT_CCNEW
+#define TCPOPT_CCNEW           12      /* T/TCP CC options (rfc1644) */
+#endif
+#ifndef TCPOPT_CCECHO
+#define TCPOPT_CCECHO          13      /* T/TCP CC options (rfc1644) */
+#endif
+
+struct tha {
+       struct in_addr src;
+       struct in_addr dst;
+       u_int port;
+};
+
+struct tcp_seq_hash {
+       struct tcp_seq_hash *nxt;
+       struct tha addr;
+       tcp_seq seq;
+       tcp_seq ack;
+};
+
+#define TSEQ_HASHSIZE 919
+
+/* These tcp optinos do not have the size octet */
+#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
+
+static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
+
+
+void
+tcp_print(register const u_char *bp, register u_int length,
+         register const u_char *bp2)
+{
+       register const struct tcphdr *tp;
+       register const struct ip *ip;
+       register u_char flags;
+       register int hlen;
+       register char ch;
+       u_short sport, dport, win, urp;
+       u_int32_t seq, ack;
+
+       tp = (struct tcphdr *)bp;
+       ip = (struct ip *)bp2;
+       ch = '\0';
+       TCHECK(*tp);
+       if (length < sizeof(*tp)) {
+               (void)printf("truncated-tcp %d", length);
+               return;
+       }
+
+       sport = ntohs(tp->th_sport);
+       dport = ntohs(tp->th_dport);
+       seq = ntohl(tp->th_seq);
+       ack = ntohl(tp->th_ack);
+       win = ntohs(tp->th_win);
+       urp = ntohs(tp->th_urp);
+
+       (void)printf("%s.%s > %s.%s: ",
+               ipaddr_string(&ip->ip_src), tcpport_string(sport),
+               ipaddr_string(&ip->ip_dst), tcpport_string(dport));
+
+       if (qflag) {
+               (void)printf("tcp %d", length - tp->th_off * 4);
+               return;
+       }
+       if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) {
+               if (flags & TH_SYN)
+                       putchar('S');
+               if (flags & TH_FIN)
+                       putchar('F');
+               if (flags & TH_RST)
+                       putchar('R');
+               if (flags & TH_PUSH)
+                       putchar('P');
+       } else
+               putchar('.');
+
+       if (!Sflag && (flags & TH_ACK)) {
+               register struct tcp_seq_hash *th;
+               register int rev;
+               struct tha tha;
+               /*
+                * Find (or record) the initial sequence numbers for
+                * this conversation.  (we pick an arbitrary
+                * collating order so there's only one entry for
+                * both directions).
+                */
+               if (sport < dport ||
+                   (sport == dport &&
+                    ip->ip_src.s_addr < ip->ip_dst.s_addr)) {
+                       tha.src = ip->ip_src, tha.dst = ip->ip_dst;
+                       tha.port = sport << 16 | dport;
+                       rev = 0;
+               } else {
+                       tha.src = ip->ip_dst, tha.dst = ip->ip_src;
+                       tha.port = dport << 16 | sport;
+                       rev = 1;
+               }
+
+               for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
+                    th->nxt; th = th->nxt)
+                       if (!memcmp((char *)&tha, (char *)&th->addr,
+                                 sizeof(th->addr)))
+                               break;
+
+               if (!th->nxt || flags & TH_SYN) {
+                       /* didn't find it or new conversation */
+                       if (th->nxt == NULL) {
+                               th->nxt = (struct tcp_seq_hash *)
+                                       calloc(1, sizeof(*th));
+                               if (th->nxt == NULL)
+                                       error("tcp_print: calloc");
+                       }
+                       th->addr = tha;
+                       if (rev)
+                               th->ack = seq, th->seq = ack - 1;
+                       else
+                               th->seq = seq, th->ack = ack - 1;
+               } else {
+                       if (rev)
+                               seq -= th->ack, ack -= th->seq;
+                       else
+                               seq -= th->seq, ack -= th->ack;
+               }
+       }
+       hlen = tp->th_off * 4;
+       if (hlen > length) {
+               (void)printf(" [bad hdr length]");
+               return;
+       }
+       length -= hlen;
+       if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
+               (void)printf(" %u:%u(%d)", seq, seq + length, length);
+       if (flags & TH_ACK)
+               (void)printf(" ack %u", ack);
+
+       (void)printf(" win %d", win);
+
+       if (flags & TH_URG)
+               (void)printf(" urg %d", urp);
+       /*
+        * Handle any options.
+        */
+       if ((hlen -= sizeof(*tp)) > 0) {
+               register const u_char *cp;
+               register int i, opt, len, datalen;
+
+               cp = (const u_char *)tp + sizeof(*tp);
+               putchar(' ');
+               ch = '<';
+               while (hlen > 0) {
+                       putchar(ch);
+                       TCHECK(*cp);
+                       opt = *cp++;
+                       if (ZEROLENOPT(opt))
+                               len = 1;
+                       else {
+                               TCHECK(*cp);
+                               len = *cp++;    /* total including type, len */
+                               if (len < 2 || len > hlen)
+                                       goto bad;
+                               --hlen;         /* account for length byte */
+                       }
+                       --hlen;                 /* account for type byte */
+                       datalen = 0;
+
+/* Bail if "l" bytes of data are not left or were not captured  */
+#define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); }
+
+                       switch (opt) {
+
+                       case TCPOPT_MAXSEG:
+                               (void)printf("mss");
+                               datalen = 2;
+                               LENCHECK(datalen);
+                               (void)printf(" %u", EXTRACT_16BITS(cp));
+
+                               break;
+
+                       case TCPOPT_EOL:
+                               (void)printf("eol");
+                               break;
+
+                       case TCPOPT_NOP:
+                               (void)printf("nop");
+                               break;
+
+                       case TCPOPT_WSCALE:
+                               (void)printf("wscale");
+                               datalen = 1;
+                               LENCHECK(datalen);
+                               (void)printf(" %u", *cp);
+                               break;
+
+                       case TCPOPT_SACKOK:
+                               (void)printf("sackOK");
+                               break;
+
+                       case TCPOPT_SACK:
+                               (void)printf("sack");
+                               datalen = len - 2;
+                               for (i = 0; i < datalen; i += 4) {
+                                       LENCHECK(i + 4);
+                                       /* block-size@relative-origin */
+                                       (void)printf(" %u@%u",
+                                           EXTRACT_16BITS(cp + i + 2),
+                                           EXTRACT_16BITS(cp + i));
+                               }
+                               if (datalen % 4)
+                                       (void)printf("[len %d]", len);
+                               break;
+
+                       case TCPOPT_ECHO:
+                               (void)printf("echo");
+                               datalen = 4;
+                               LENCHECK(datalen);
+                               (void)printf(" %u", EXTRACT_32BITS(cp));
+                               break;
+
+                       case TCPOPT_ECHOREPLY:
+                               (void)printf("echoreply");
+                               datalen = 4;
+                               LENCHECK(datalen);
+                               (void)printf(" %u", EXTRACT_32BITS(cp));
+                               break;
+
+                       case TCPOPT_TIMESTAMP:
+                               (void)printf("timestamp");
+                               datalen = 8;
+                               LENCHECK(4);
+                               (void)printf(" %u", EXTRACT_32BITS(cp));
+                               LENCHECK(datalen);
+                               (void)printf(" %u", EXTRACT_32BITS(cp + 4));
+                               break;
+
+                       case TCPOPT_CC:
+                               (void)printf("cc");
+                               datalen = 4;
+                               LENCHECK(datalen);
+                               (void)printf(" %u", EXTRACT_32BITS(cp));
+                               break;
+
+                       case TCPOPT_CCNEW:
+                               (void)printf("ccnew");
+                               datalen = 4;
+                               LENCHECK(datalen);
+                               (void)printf(" %u", EXTRACT_32BITS(cp));
+                               break;
+
+                       case TCPOPT_CCECHO:
+                               (void)printf("ccecho");
+                               datalen = 4;
+                               LENCHECK(datalen);
+                               (void)printf(" %u", EXTRACT_32BITS(cp));
+                               break;
+
+                       default:
+                               (void)printf("opt-%d:", opt);
+                               datalen = len - 2;
+                               for (i = 0; i < datalen; ++i) {
+                                       LENCHECK(i);
+                                       (void)printf("%02x", cp[i]);
+                               }
+                               break;
+                       }
+
+                       /* Account for data printed */
+                       cp += datalen;
+                       hlen -= datalen;
+
+                       /* Check specification against observed length */
+                       ++datalen;                      /* option octet */
+                       if (!ZEROLENOPT(opt))
+                               ++datalen;              /* size octet */
+                       if (datalen != len)
+                               (void)printf("[len %d]", len);
+                       ch = ',';
+                       if (opt == TCPOPT_EOL)
+                               break;
+               }
+               putchar('>');
+       }
+       return;
+bad:
+       fputs("[bad opt]", stdout);
+       if (ch != '\0')
+               putchar('>');
+       return;
+trunc:
+       fputs("[|tcp]", stdout);
+       if (ch != '\0')
+               putchar('>');
+}
+
diff --git a/tcpdump.tproj/print-tftp.c b/tcpdump.tproj/print-tftp.c
new file mode 100644 (file)
index 0000000..9db5775
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print trivial file transfer protocol packets.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-tftp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#include <arpa/tftp.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/* op code to string mapping */
+static struct tok op2str[] = {
+       { RRQ,          "RRQ" },        /* read request */
+       { WRQ,          "WRQ" },        /* write request */
+       { DATA,         "DATA" },       /* data packet */
+       { ACK,          "ACK" },        /* acknowledgement */
+       { ERROR,        "ERROR" },      /* error code */
+       { 0,            NULL }
+};
+
+/* error code to string mapping */
+static struct tok err2str[] = {
+       { EUNDEF,       "EUNDEF" },     /* not defined */
+       { ENOTFOUND,    "ENOTFOUND" },  /* file not found */
+       { EACCESS,      "EACCESS" },    /* access violation */
+       { ENOSPACE,     "ENOSPACE" },   /* disk full or allocation exceeded */
+       { EBADOP,       "EBADOP" },     /* illegal TFTP operation */
+       { EBADID,       "EBADID" },     /* unknown transfer ID */
+       { EEXISTS,      "EEXISTS" },    /* file already exists */
+       { ENOUSER,      "ENOUSER" },    /* no such user */
+       { 0,            NULL }
+};
+
+/*
+ * Print trivial file transfer program requests
+ */
+void
+tftp_print(register const u_char *bp, u_int length)
+{
+       register const struct tftphdr *tp;
+       register const char *cp;
+       register const u_char *p;
+       register int opcode, i;
+       static char tstr[] = " [|tftp]";
+
+       tp = (const struct tftphdr *)bp;
+
+       /* Print length */
+       printf(" %d", length);
+
+       /* Print tftp request type */
+       TCHECK(tp->th_opcode);
+       opcode = ntohs(tp->th_opcode);
+       cp = tok2str(op2str, "tftp-#%d", opcode);
+       printf(" %s", cp);
+       /* Bail if bogus opcode */
+       if (*cp == 't')
+               return;
+
+       switch (opcode) {
+
+       case RRQ:
+       case WRQ:
+               /*
+                * XXX Not all arpa/tftp.h's specify th_stuff as any
+                * array; use address of th_block instead
+                */
+#ifdef notdef
+               p = (u_char *)tp->th_stuff;
+#else
+               p = (u_char *)&tp->th_block;
+#endif
+               fputs(" \"", stdout);
+               i = fn_print(p, snapend);
+               putchar('"');
+               if (i)
+                       goto trunc;
+               break;
+
+       case ACK:
+       case DATA:
+               TCHECK(tp->th_block);
+               printf(" block %d", ntohs(tp->th_block));
+               break;
+
+       case ERROR:
+               /* Print error code string */
+               TCHECK(tp->th_code);
+               printf(" %s ", tok2str(err2str, "tftp-err-#%d \"",
+                                      ntohs(tp->th_code)));
+               /* Print error message string */
+               i = fn_print((const u_char *)tp->th_data, snapend);
+               putchar('"');
+               if (i)
+                       goto trunc;
+               break;
+
+       default:
+               /* We shouldn't get here */
+               printf("(unknown #%d)", opcode);
+               break;
+       }
+       return;
+trunc:
+       fputs(tstr, stdout);
+       return;
+}
diff --git a/tcpdump.tproj/print-udp.c b/tcpdump.tproj/print-udp.c
new file mode 100644 (file)
index 0000000..f8e4366
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-udp.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#undef NOERROR                                 /* Solaris sucks */
+#undef T_UNSPEC                                        /* SINIX does too */
+#include <arpa/nameser.h>
+#include <arpa/tftp.h>
+
+#include <rpc/rpc.h>
+
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "appletalk.h"
+
+#include "nfsv2.h"
+#include "bootp.h"
+
+struct rtcphdr {
+       u_short rh_flags;       /* T:2 P:1 CNT:5 PT:8 */
+       u_short rh_len;         /* length of message (in words) */
+       u_int rh_ssrc;          /* synchronization src id */
+};
+
+typedef struct {
+       u_int upper;            /* more significant 32 bits */
+       u_int lower;            /* less significant 32 bits */
+} ntp64;
+
+/*
+ * Sender report.
+ */
+struct rtcp_sr {
+       ntp64 sr_ntp;           /* 64-bit ntp timestamp */
+       u_int sr_ts;            /* reference media timestamp */
+       u_int sr_np;            /* no. packets sent */
+       u_int sr_nb;            /* no. bytes sent */
+};
+
+/*
+ * Receiver report.
+ * Time stamps are middle 32-bits of ntp timestamp.
+ */
+struct rtcp_rr {
+       u_int rr_srcid;         /* sender being reported */
+       u_int rr_nl;            /* no. packets lost */
+       u_int rr_ls;            /* extended last seq number received */
+       u_int rr_dv;            /* jitter (delay variance) */
+       u_int rr_lsr;           /* orig. ts from last rr from this src  */
+       u_int rr_dlsr;          /* time from recpt of last rr to xmit time */
+};
+
+/*XXX*/
+#define RTCP_PT_SR     200
+#define RTCP_PT_RR     201
+#define RTCP_PT_SDES   202
+#define        RTCP_SDES_CNAME 1
+#define        RTCP_SDES_NAME  2
+#define        RTCP_SDES_EMAIL 3
+#define        RTCP_SDES_PHONE 4
+#define        RTCP_SDES_LOC   5
+#define        RTCP_SDES_TOOL  6
+#define        RTCP_SDES_NOTE  7
+#define        RTCP_SDES_PRIV  8
+#define RTCP_PT_BYE    203
+#define RTCP_PT_APP    204
+
+static void
+vat_print(const void *hdr, u_int len, register const struct udphdr *up)
+{
+       /* vat/vt audio */
+       u_int ts = *(u_short *)hdr;
+       if ((ts & 0xf060) != 0) {
+               /* probably vt */
+               (void)printf(" udp/vt %u %d / %d",
+                            (u_int32_t)(ntohs(up->uh_ulen) - sizeof(*up)),
+                            ts & 0x3ff, ts >> 10);
+       } else {
+               /* probably vat */
+               u_int i0 = ntohl(((u_int *)hdr)[0]);
+               u_int i1 = ntohl(((u_int *)hdr)[1]);
+               printf(" udp/vat %u c%d %u%s",
+                       (u_int32_t)(ntohs(up->uh_ulen) - sizeof(*up) - 8),
+                       i0 & 0xffff,
+                       i1, i0 & 0x800000? "*" : "");
+               /* audio format */
+               if (i0 & 0x1f0000)
+                       printf(" f%d", (i0 >> 16) & 0x1f);
+               if (i0 & 0x3f000000)
+                       printf(" s%d", (i0 >> 24) & 0x3f);
+       }
+}
+
+static void
+rtp_print(const void *hdr, u_int len, register const struct udphdr *up)
+{
+       /* rtp v1 or v2 */
+       u_int *ip = (u_int *)hdr;
+       u_int hasopt, hasext, contype, hasmarker;
+       u_int i0 = ntohl(((u_int *)hdr)[0]);
+       u_int i1 = ntohl(((u_int *)hdr)[1]);
+       u_int dlen = ntohs(up->uh_ulen) - sizeof(*up) - 8;
+       const char * ptype;
+
+       ip += 2;
+       len >>= 2;
+       len -= 2;
+       hasopt = 0;
+       hasext = 0;
+       if ((i0 >> 30) == 1) {
+               /* rtp v1 */
+               hasopt = i0 & 0x800000;
+               contype = (i0 >> 16) & 0x3f;
+               hasmarker = i0 & 0x400000;
+               ptype = "rtpv1";
+       } else {
+               /* rtp v2 */
+               hasext = i0 & 0x10000000;
+               contype = (i0 >> 16) & 0x7f;
+               hasmarker = i0 & 0x800000;
+               dlen -= 4;
+               ptype = "rtp";
+               ip += 1;
+               len -= 1;
+       }
+       printf(" udp/%s %d c%d %s%s %d %u",
+               ptype,
+               dlen,
+               contype,
+               (hasopt || hasext)? "+" : "",
+               hasmarker? "*" : "",
+               i0 & 0xffff,
+               i1);
+       if (vflag) {
+               printf(" %u", i1);
+               if (hasopt) {
+                       u_int i2, optlen;
+                       do {
+                               i2 = ip[0];
+                               optlen = (i2 >> 16) & 0xff;
+                               if (optlen == 0 || optlen > len) {
+                                       printf(" !opt");
+                                       return;
+                               }
+                               ip += optlen;
+                               len -= optlen;
+                       } while ((int)i2 >= 0);
+               }
+               if (hasext) {
+                       u_int i2, extlen;
+                       i2 = ip[0];
+                       extlen = (i2 & 0xffff) + 1;
+                       if (extlen > len) {
+                               printf(" !ext");
+                               return;
+                       }
+                       ip += extlen;
+               }
+               if (contype == 0x1f) /*XXX H.261 */
+                       printf(" 0x%04x", ip[0] >> 16);
+       }
+}
+
+static const u_char *
+rtcp_print(const u_char *hdr, const u_char *ep)
+{
+       /* rtp v2 control (rtcp) */
+       struct rtcp_rr *rr = 0;
+       struct rtcp_sr *sr;
+       struct rtcphdr *rh = (struct rtcphdr *)hdr;
+       u_int len;
+       u_short flags;
+       int cnt;
+       double ts, dts;
+       if ((u_char *)(rh + 1) > ep) {
+               printf(" [|rtcp]");
+               return (ep);
+       }
+       len = (ntohs(rh->rh_len) + 1) * 4;
+       flags = ntohs(rh->rh_flags);
+       cnt = (flags >> 8) & 0x1f;
+       switch (flags & 0xff) {
+       case RTCP_PT_SR:
+               sr = (struct rtcp_sr *)(rh + 1);
+               printf(" sr");
+               if (len != cnt * sizeof(*rr) + sizeof(*sr) + sizeof(*rh))
+                       printf(" [%d]", len);
+               if (vflag)
+                 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
+               if ((u_char *)(sr + 1) > ep) {
+                       printf(" [|rtcp]");
+                       return (ep);
+               }
+               ts = (double)((u_int32_t)ntohl(sr->sr_ntp.upper)) +
+                   ((double)((u_int32_t)ntohl(sr->sr_ntp.lower)) /
+                   4294967296.0);
+               printf(" @%.2f %u %up %ub", ts, (u_int32_t)ntohl(sr->sr_ts),
+                   (u_int32_t)ntohl(sr->sr_np), (u_int32_t)ntohl(sr->sr_nb));
+               rr = (struct rtcp_rr *)(sr + 1);
+               break;
+       case RTCP_PT_RR:
+               printf(" rr");
+               if (len != cnt * sizeof(*rr) + sizeof(*rh))
+                       printf(" [%d]", len);
+               rr = (struct rtcp_rr *)(rh + 1);
+               if (vflag)
+                 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
+               break;
+       case RTCP_PT_SDES:
+               printf(" sdes %d", len);
+               if (vflag)
+                 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
+               cnt = 0;
+               break;
+       case RTCP_PT_BYE:
+               printf(" bye %d", len);
+               if (vflag)
+                 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
+               cnt = 0;
+               break;
+       default:
+               printf(" type-0x%x %d", flags & 0xff, len);
+               cnt = 0;
+               break;
+       }
+       if (cnt > 1)
+               printf(" c%d", cnt);
+       while (--cnt >= 0) {
+               if ((u_char *)(rr + 1) > ep) {
+                       printf(" [|rtcp]");
+                       return (ep);
+               }
+               if (vflag)
+                       printf(" %u", (u_int32_t)ntohl(rr->rr_srcid));
+               ts = (double)((u_int32_t)ntohl(rr->rr_lsr)) / 65536.;
+               dts = (double)((u_int32_t)ntohl(rr->rr_dlsr)) / 65536.;
+               printf(" %ul %us %uj @%.2f+%.2f",
+                   (u_int32_t)ntohl(rr->rr_nl) & 0x00ffffff,
+                   (u_int32_t)ntohl(rr->rr_ls),
+                   (u_int32_t)ntohl(rr->rr_dv), ts, dts);
+       }
+       return (hdr + len);
+}
+
+/* XXX probably should use getservbyname() and cache answers */
+#define TFTP_PORT 69           /*XXX*/
+#define KERBEROS_PORT 88       /*XXX*/
+#define SUNRPC_PORT 111                /*XXX*/
+#define SNMP_PORT 161          /*XXX*/
+#define NTP_PORT 123           /*XXX*/
+#define SNMPTRAP_PORT 162      /*XXX*/
+#define RIP_PORT 520           /*XXX*/
+#define KERBEROS_SEC_PORT 750  /*XXX*/
+
+void
+udp_print(register const u_char *bp, u_int length, register const u_char *bp2)
+{
+       register const struct udphdr *up;
+       register const struct ip *ip;
+       register const u_char *cp;
+       register const u_char *ep = bp + length;
+       u_short sport, dport, ulen;
+
+       if (ep > snapend)
+               ep = snapend;
+       up = (struct udphdr *)bp;
+       ip = (struct ip *)bp2;
+       cp = (u_char *)(up + 1);
+       if (cp > snapend) {
+               printf("[|udp]");
+               return;
+       }
+       if (length < sizeof(struct udphdr)) {
+               (void)printf(" truncated-udp %d", length);
+               return;
+       }
+       length -= sizeof(struct udphdr);
+
+       sport = ntohs(up->uh_sport);
+       dport = ntohs(up->uh_dport);
+       ulen = ntohs(up->uh_ulen);
+       if (packettype) {
+               register struct rpc_msg *rp;
+               enum msg_type direction;
+
+               switch (packettype) {
+
+               case PT_VAT:
+                       (void)printf("%s.%s > %s.%s:",
+                               ipaddr_string(&ip->ip_src),
+                               udpport_string(sport),
+                               ipaddr_string(&ip->ip_dst),
+                               udpport_string(dport));
+                       vat_print((void *)(up + 1), length, up);
+                       break;
+
+               case PT_WB:
+                       (void)printf("%s.%s > %s.%s:",
+                               ipaddr_string(&ip->ip_src),
+                               udpport_string(sport),
+                               ipaddr_string(&ip->ip_dst),
+                               udpport_string(dport));
+                       wb_print((void *)(up + 1), length);
+                       break;
+
+               case PT_RPC:
+                       rp = (struct rpc_msg *)(up + 1);
+                       direction = (enum msg_type)ntohl(rp->rm_direction);
+                       if (direction == CALL)
+                               sunrpcrequest_print((u_char *)rp, length,
+                                   (u_char *)ip);
+                       else
+                               nfsreply_print((u_char *)rp, length,
+                                   (u_char *)ip);                      /*XXX*/
+                       break;
+
+               case PT_RTP:
+                       (void)printf("%s.%s > %s.%s:",
+                               ipaddr_string(&ip->ip_src),
+                               udpport_string(sport),
+                               ipaddr_string(&ip->ip_dst),
+                               udpport_string(dport));
+                       rtp_print((void *)(up + 1), length, up);
+                       break;
+
+               case PT_RTCP:
+                       (void)printf("%s.%s > %s.%s:",
+                               ipaddr_string(&ip->ip_src),
+                               udpport_string(sport),
+                               ipaddr_string(&ip->ip_dst),
+                               udpport_string(dport));
+                       while (cp < ep)
+                               cp = rtcp_print(cp, ep);
+                       break;
+               }
+               return;
+       }
+
+       if (!qflag) {
+               register struct rpc_msg *rp;
+               enum msg_type direction;
+
+               rp = (struct rpc_msg *)(up + 1);
+               if (TTEST(rp->rm_direction)) {
+                       direction = (enum msg_type)ntohl(rp->rm_direction);
+                       if (dport == NFS_PORT && direction == CALL) {
+                               nfsreq_print((u_char *)rp, length,
+                                   (u_char *)ip);
+                               return;
+                       }
+                       if (sport == NFS_PORT && direction == REPLY) {
+                               nfsreply_print((u_char *)rp, length,
+                                   (u_char *)ip);
+                               return;
+                       }
+#ifdef notdef
+                       if (dport == SUNRPC_PORT && direction == CALL) {
+                               sunrpcrequest_print((u_char *)rp, length, (u_char *)ip);
+                               return;
+                       }
+#endif
+               }
+               if (TTEST(((struct LAP *)cp)->type) &&
+                   ((struct LAP *)cp)->type == lapDDP &&
+                   (atalk_port(sport) || atalk_port(dport))) {
+                       if (vflag)
+                               fputs("kip ", stdout);
+                       atalk_print(cp, length);
+                       return;
+               }
+       }
+       (void)printf("%s.%s > %s.%s:",
+               ipaddr_string(&ip->ip_src), udpport_string(sport),
+               ipaddr_string(&ip->ip_dst), udpport_string(dport));
+
+       if (!qflag) {
+#define ISPORT(p) (dport == (p) || sport == (p))
+               if (ISPORT(NAMESERVER_PORT))
+                       ns_print((const u_char *)(up + 1), length);
+               else if (ISPORT(TFTP_PORT))
+                       tftp_print((const u_char *)(up + 1), length);
+               else if (ISPORT(IPPORT_BOOTPC) || ISPORT(IPPORT_BOOTPS))
+                       bootp_print((const u_char *)(up + 1), length,
+                           sport, dport);
+               else if (ISPORT(RIP_PORT))
+                       rip_print((const u_char *)(up + 1), length);
+               else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT))
+                       snmp_print((const u_char *)(up + 1), length);
+               else if (ISPORT(NTP_PORT))
+                       ntp_print((const u_char *)(up + 1), length);
+               else if (ISPORT(KERBEROS_PORT) || ISPORT(KERBEROS_SEC_PORT))
+                       krb_print((const void *)(up + 1), length);
+               else if (dport == 3456)
+                       vat_print((const void *)(up + 1), length, up);
+               /*
+                * Kludge in test for whiteboard packets.
+                */
+               else if (dport == 4567)
+                       wb_print((const void *)(up + 1), length);
+               else
+                       (void)printf(" udp %u",
+                           (u_int32_t)(ulen - sizeof(*up)));
+#undef ISPORT
+       } else
+               (void)printf(" udp %u", (u_int32_t)(ulen - sizeof(*up)));
+}
diff --git a/tcpdump.tproj/print-wb.c b/tcpdump.tproj/print-wb.c
new file mode 100644 (file)
index 0000000..3b0c160
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-wb.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+/* XXX need to add byte-swapping macros! */
+
+/*
+ * Largest packet size.  Everything should fit within this space.
+ * For instance, multiline objects are sent piecewise.
+ */
+#define MAXFRAMESIZE 1024
+
+/*
+ * Multiple drawing ops can be sent in one packet.  Each one starts on a
+ * an even multiple of DOP_ALIGN bytes, which must be a power of two.
+ */
+#define DOP_ALIGN 4
+#define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
+#define DOP_NEXT(d)\
+       ((struct dophdr *)((u_char *)(d) + \
+                         DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d)))))
+
+/*
+ * Format of the whiteboard packet header.
+ * The transport level header.
+ */
+struct pkt_hdr {
+       u_int32_t ph_src;               /* site id of source */
+       u_int32_t ph_ts;                /* time stamp (for skew computation) */
+       u_short ph_version;     /* version number */
+       u_char ph_type;         /* message type */
+       u_char ph_flags;        /* message flags */
+};
+
+/* Packet types */
+#define PT_DRAWOP      0       /* drawing operation */
+#define PT_ID          1       /* announcement packet */
+#define PT_RREQ                2       /* repair request */
+#define PT_RREP                3       /* repair reply */
+#define PT_KILL                4       /* terminate participation */
+#define PT_PREQ         5       /* page vector request */
+#define PT_PREP         7       /* page vector reply */
+
+/* flags */
+#define PF_USER                0x01    /* hint that packet has interactive data */
+#define PF_VIS         0x02    /* only visible ops wanted */
+
+struct PageID {
+       u_int32_t p_sid;                /* session id of initiator */
+       u_int32_t p_uid;                /* page number */
+};
+
+struct dophdr {
+       u_int32_t  dh_ts;               /* sender's timestamp */
+       u_short dh_len;         /* body length */
+       u_char  dh_flags;
+       u_char  dh_type;        /* body type */
+       /* body follows */
+};
+/*
+ * Drawing op sub-types.
+ */
+#define DT_RECT         2
+#define DT_LINE         3
+#define DT_ML           4
+#define DT_DEL          5
+#define DT_XFORM        6
+#define DT_ELL          7
+#define DT_CHAR         8
+#define DT_STR          9
+#define DT_NOP          10
+#define DT_PSCODE       11
+#define DT_PSCOMP       12
+#define DT_REF          13
+#define DT_SKIP         14
+#define DT_HOLE         15
+#define DT_MAXTYPE      15
+
+/*
+ * A drawing operation.
+ */
+struct pkt_dop {
+       struct PageID pd_page;  /* page that operations apply to */
+       u_int32_t       pd_sseq;        /* start sequence number */
+       u_int32_t       pd_eseq;        /* end sequence number */
+       /* drawing ops follow */
+};
+
+/*
+ * A repair request.
+ */
+struct pkt_rreq {
+        u_int32_t pr_id;           /* source id of drawops to be repaired */
+        struct PageID pr_page;           /* page of drawops */
+        u_int32_t pr_sseq;         /* start seqno */
+        u_int32_t pr_eseq;         /* end seqno */
+};
+
+/*
+ * A repair reply.
+ */
+struct pkt_rrep {
+       u_int32_t pr_id;        /* original site id of ops  */
+       struct pkt_dop pr_dop;
+       /* drawing ops follow */
+};
+
+struct id_off {
+        u_int32_t id;
+        u_int32_t off;
+};
+
+struct pgstate {
+       u_int32_t slot;
+       struct PageID page;
+       u_short nid;
+       u_short rsvd;
+        /* seqptr's */
+};
+
+/*
+ * An announcement packet.
+ */
+struct pkt_id {
+       u_int32_t pi_mslot;
+        struct PageID    pi_mpage;        /* current page */
+       struct pgstate pi_ps;
+        /* seqptr's */
+        /* null-terminated site name */
+};
+
+struct pkt_preq {
+        struct PageID  pp_page;
+        u_int32_t  pp_low;
+        u_int32_t  pp_high;
+};
+
+struct pkt_prep {
+        u_int32_t  pp_n;           /* size of pageid array */
+        /* pgstate's follow */
+};
+
+static int
+wb_id(const struct pkt_id *id, u_int len)
+{
+       int i;
+       const char *cp;
+       const struct id_off *io;
+       char c;
+       int nid;
+
+       printf(" wb-id:");
+       len -= sizeof(*id);
+       if (len < 0 || (u_char *)(id + 1) > snapend)
+               return (-1);
+
+       printf(" %u/%s:%u (max %u/%s:%u) ",
+              (u_int32_t)ntohl(id->pi_ps.slot),
+              ipaddr_string(&id->pi_ps.page.p_sid),
+              (u_int32_t)ntohl(id->pi_ps.page.p_uid),
+              (u_int32_t)ntohl(id->pi_mslot),
+              ipaddr_string(&id->pi_mpage.p_sid),
+              (u_int32_t)ntohl(id->pi_mpage.p_uid));
+
+       nid = ntohs(id->pi_ps.nid);
+       len -= sizeof(*io) * nid;
+       io = (struct id_off *)(id + 1);
+       cp = (char *)(io + nid);
+       if ((u_char *)cp + len <= snapend) {
+               putchar('"');
+               (void)fn_print((u_char *)cp, (u_char *)cp + len);
+               putchar('"');
+       }
+
+       c = '<';
+       for (i = 0; i < nid && (u_char *)io < snapend; ++io, ++i) {
+               printf("%c%s:%u",
+                   c, ipaddr_string(&io->id), (u_int32_t)ntohl(io->off));
+               c = ',';
+       }
+       if (i >= nid) {
+               printf(">");
+               return (0);
+       }
+       return (-1);
+}
+
+static int
+wb_rreq(const struct pkt_rreq *rreq, u_int len)
+{
+       printf(" wb-rreq:");
+       if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
+               return (-1);
+
+       printf(" please repair %s %s:%u<%u:%u>",
+              ipaddr_string(&rreq->pr_id),
+              ipaddr_string(&rreq->pr_page.p_sid),
+              (u_int32_t)ntohl(rreq->pr_page.p_uid),
+              (u_int32_t)ntohl(rreq->pr_sseq),
+              (u_int32_t)ntohl(rreq->pr_eseq));
+       return (0);
+}
+
+static int
+wb_preq(const struct pkt_preq *preq, u_int len)
+{
+       printf(" wb-preq:");
+       if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
+               return (-1);
+
+       printf(" need %u/%s:%u",
+              (u_int32_t)ntohl(preq->pp_low),
+              ipaddr_string(&preq->pp_page.p_sid),
+              (u_int32_t)ntohl(preq->pp_page.p_uid));
+       return (0);
+}
+
+static int
+wb_prep(const struct pkt_prep *prep, u_int len)
+{
+       int n;
+       const struct pgstate *ps;
+       const u_char *ep = snapend;
+
+       printf(" wb-prep:");
+       if (len < sizeof(*prep)) {
+               return (-1);
+       }
+       n = ntohl(prep->pp_n);
+       ps = (const struct pgstate *)(prep + 1);
+       while (--n >= 0 && (u_char *)ps < ep) {
+               const struct id_off *io, *ie;
+               char c = '<';
+
+               printf(" %u/%s:%u",
+                   (u_int32_t)ntohl(ps->slot),
+                   ipaddr_string(&ps->page.p_sid),
+                   (u_int32_t)ntohl(ps->page.p_uid));
+               io = (struct id_off *)(ps + 1);
+               for (ie = io + ps->nid; io < ie && (u_char *)io < ep; ++io) {
+                       printf("%c%s:%u", c, ipaddr_string(&io->id),
+                           (u_int32_t)ntohl(io->off));
+                       c = ',';
+               }
+               printf(">");
+               ps = (struct pgstate *)io;
+       }
+       return ((u_char *)ps <= ep? 0 : -1);
+}
+
+
+char *dopstr[] = {
+       "dop-0!",
+       "dop-1!",
+       "RECT",
+       "LINE",
+       "ML",
+       "DEL",
+       "XFORM",
+       "ELL",
+       "CHAR",
+       "STR",
+       "NOP",
+       "PSCODE",
+       "PSCOMP",
+       "REF",
+       "SKIP",
+       "HOLE",
+};
+
+static int
+wb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es)
+{
+       printf(" <");
+       for ( ; ss <= es; ++ss) {
+               register int t = dh->dh_type;
+
+               if (t > DT_MAXTYPE)
+                       printf(" dop-%d!", t);
+               else {
+                       printf(" %s", dopstr[t]);
+                       if (t == DT_SKIP || t == DT_HOLE) {
+                               int ts = ntohl(dh->dh_ts);
+                               printf("%d", ts - ss + 1);
+                               if (ss > ts || ts > es) {
+                                       printf("[|]");
+                                       if (ts < ss)
+                                               return (0);
+                               }
+                               ss = ts;
+                       }
+               }
+               dh = DOP_NEXT(dh);
+               if ((u_char *)dh > snapend) {
+                       printf("[|wb]");
+                       break;
+               }
+       }
+       printf(" >");
+       return (0);
+}
+
+static int
+wb_rrep(const struct pkt_rrep *rrep, u_int len)
+{
+       const struct pkt_dop *dop = &rrep->pr_dop;
+
+       printf(" wb-rrep:");
+       len -= sizeof(*rrep);
+       if (len < 0 || (u_char *)(rrep + 1) > snapend)
+               return (-1);
+
+       printf(" for %s %s:%u<%u:%u>",
+           ipaddr_string(&rrep->pr_id),
+           ipaddr_string(&dop->pd_page.p_sid),
+           (u_int32_t)ntohl(dop->pd_page.p_uid),
+           (u_int32_t)ntohl(dop->pd_sseq),
+           (u_int32_t)ntohl(dop->pd_eseq));
+
+       if (vflag)
+               return (wb_dops((const struct dophdr *)(dop + 1),
+                   ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
+       return (0);
+}
+
+static int
+wb_drawop(const struct pkt_dop *dop, u_int len)
+{
+       printf(" wb-dop:");
+       len -= sizeof(*dop);
+       if (len < 0 || (u_char *)(dop + 1) > snapend)
+               return (-1);
+
+       printf(" %s:%u<%u:%u>",
+           ipaddr_string(&dop->pd_page.p_sid),
+           (u_int32_t)ntohl(dop->pd_page.p_uid),
+           (u_int32_t)ntohl(dop->pd_sseq),
+           (u_int32_t)ntohl(dop->pd_eseq));
+
+       if (vflag)
+               return (wb_dops((const struct dophdr *)(dop + 1),
+                               ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
+       return (0);
+}
+
+/*
+ * Print whiteboard multicast packets.
+ */
+void
+wb_print(register const void *hdr, register u_int len)
+{
+       register const struct pkt_hdr *ph;
+
+       ph = (const struct pkt_hdr *)hdr;
+       len -= sizeof(*ph);
+       if (len < 0 || (u_char *)(ph + 1) <= snapend) {
+               if (ph->ph_flags)
+                       printf("*");
+               switch (ph->ph_type) {
+
+               case PT_KILL:
+                       printf(" wb-kill");
+                       return;
+
+               case PT_ID:
+                       if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
+                               return;
+                       break;
+
+               case PT_RREQ:
+                       if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
+                               return;
+                       break;
+
+               case PT_RREP:
+                       if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
+                               return;
+                       break;
+
+               case PT_DRAWOP:
+                       if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
+                               return;
+                       break;
+
+               case PT_PREQ:
+                       if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
+                               return;
+                       break;
+
+               case PT_PREP:
+                       if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
+                               return;
+                       break;
+
+               default:
+                       printf(" wb-%d!", ph->ph_type);
+                       return;
+               }
+       }
+       printf("[|wb]");
+}
diff --git a/tcpdump.tproj/strcasecmp.c b/tcpdump.tproj/strcasecmp.c
new file mode 100644 (file)
index 0000000..edb886a
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific written prior permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strcasecmp.c 5.5 (Berkeley) 11/24/87";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include "interface.h"
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static u_char charmap[] = {
+       '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+       '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+       '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+       '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+       '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+       '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+       '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+       '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+       '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+       '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+       '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+       '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+       '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+       '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+       '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+       '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+       '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+       '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+       '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+       '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+       '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+       '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+       '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+       '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+       '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+       '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+       '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+       '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+       '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+       '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+       '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+       '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+__private_extern__
+int
+strcasecmp(s1, s2)
+       const char *s1, *s2;
+{
+       register u_char *cm = charmap,
+                       *us1 = (u_char *)s1,
+                       *us2 = (u_char *)s2;
+
+       while (cm[*us1] == cm[*us2++])
+               if (*us1++ == '\0')
+                       return(0);
+       return(cm[*us1] - cm[*--us2]);
+}
+
+int
+strncasecmp(s1, s2, n)
+       const char *s1, *s2;
+       register int n;
+{
+       register u_char *cm = charmap,
+                       *us1 = (u_char *)s1,
+                       *us2 = (u_char *)s2;
+
+       while (--n >= 0 && cm[*us1] == cm[*us2++])
+               if (*us1++ == '\0')
+                       return(0);
+       return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
+}
diff --git a/tcpdump.tproj/tcpdump.c b/tcpdump.tproj/tcpdump.c
new file mode 100644 (file)
index 0000000..5ad2561
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996\n\
+The Regents of the University of California.  All rights reserved.\n";
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/tcpdump.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)";
+#endif
+
+/*
+ * tcpdump - monitor tcp/ip traffic on an ethernet.
+ *
+ * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
+ * Mercilessly hacked and occasionally improved since then via the
+ * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#include <pcap.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "machdep.h"
+
+int fflag;                     /* don't translate "foreign" IP address */
+int nflag;                     /* leave addresses as numbers */
+int Nflag;                     /* remove domains from printed host names */
+int pflag;                     /* don't go promiscuous */
+int qflag;                     /* quick (shorter) output */
+int tflag = 1;                 /* print packet arrival time */
+int eflag;                     /* print ethernet header */
+int vflag;                     /* verbose */
+int xflag;                     /* print packet in hex */
+int Oflag = 1;                 /* run filter code optimizer */
+int Sflag;                     /* print raw TCP sequence numbers */
+int packettype;
+
+int dflag;                     /* print filter code */
+
+char *program_name;
+
+int32_t thiszone;              /* seconds offset from gmt to local time */
+
+/* Externs */
+extern void bpf_dump(struct bpf_program *, int);
+
+/* Forwards */
+RETSIGTYPE cleanup(int);
+extern __dead void usage(void) __attribute__((volatile));
+
+/* Length of saved portion of packet. */
+int snaplen = DEFAULT_SNAPLEN;
+
+struct printer {
+       pcap_handler f;
+       int type;
+};
+
+/* XXX needed if using old bpf.h */
+#ifndef DLT_ATM_RFC1483
+#define DLT_ATM_RFC1483 11
+#endif
+
+static struct printer printers[] = {
+       { ether_if_print,       DLT_EN10MB },
+       { ether_if_print,       DLT_IEEE802 },
+       { sl_if_print,          DLT_SLIP },
+       { ppp_if_print,         DLT_PPP },
+       { fddi_if_print,        DLT_FDDI },
+       { null_if_print,        DLT_NULL },
+       { atm_if_print,         DLT_ATM_RFC1483 },
+       { NULL,                 0 },
+};
+
+static pcap_handler
+lookup_printer(int type)
+{
+       struct printer *p;
+
+       for (p = printers; p->f; ++p)
+               if (type == p->type)
+                       return p->f;
+
+       error("unknown data link type 0x%x", type);
+       /* NOTREACHED */
+}
+
+static pcap_t *pd;
+
+extern int optind;
+extern int opterr;
+extern char *optarg;
+
+int
+main(int argc, char **argv)
+{
+       register int cnt, op, i;
+       bpf_u_int32 localnet, netmask;
+       register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
+       pcap_handler printer;
+       struct bpf_program fcode;
+       u_char *pcap_userdata;
+       char ebuf[PCAP_ERRBUF_SIZE];
+
+       cnt = -1;
+       device = NULL;
+       infile = NULL;
+       RFileName = NULL;
+       WFileName = NULL;
+       if ((cp = strrchr(argv[0], '/')) != NULL)
+               program_name = cp + 1;
+       else
+               program_name = argv[0];
+
+       if (abort_on_misalignment(ebuf) < 0)
+               error("%s", ebuf);
+
+       opterr = 0;
+       while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:StT:vw:xY")) != -1)
+               switch (op) {
+               case 'c':
+                       cnt = atoi(optarg);
+                       if (cnt <= 0)
+                               error("invalid packet count %s", optarg);
+                       break;
+
+               case 'd':
+                       ++dflag;
+                       break;
+
+               case 'e':
+                       ++eflag;
+                       break;
+
+               case 'f':
+                       ++fflag;
+                       break;
+
+               case 'F':
+                       infile = optarg;
+                       break;
+
+               case 'i':
+                       device = optarg;
+                       break;
+
+               case 'l':
+#ifdef HAVE_SETLINEBUF
+                       setlinebuf(stdout);
+#else
+                       setvbuf(stdout, NULL, _IOLBF, 0);
+#endif
+                       break;
+
+               case 'n':
+                       ++nflag;
+                       break;
+
+               case 'N':
+                       ++Nflag;
+                       break;
+
+               case 'O':
+                       Oflag = 0;
+                       break;
+
+               case 'p':
+                       ++pflag;
+                       break;
+
+               case 'q':
+                       ++qflag;
+                       break;
+
+               case 'r':
+                       RFileName = optarg;
+                       break;
+
+               case 's':
+                       snaplen = atoi(optarg);
+                       if (snaplen <= 0)
+                               error("invalid snaplen %s", optarg);
+                       break;
+
+               case 'S':
+                       ++Sflag;
+                       break;
+
+               case 't':
+                       --tflag;
+                       break;
+
+               case 'T':
+                       if (strcasecmp(optarg, "vat") == 0)
+                               packettype = PT_VAT;
+                       else if (strcasecmp(optarg, "wb") == 0)
+                               packettype = PT_WB;
+                       else if (strcasecmp(optarg, "rpc") == 0)
+                               packettype = PT_RPC;
+                       else if (strcasecmp(optarg, "rtp") == 0)
+                               packettype = PT_RTP;
+                       else if (strcasecmp(optarg, "rtcp") == 0)
+                               packettype = PT_RTCP;
+                       else
+                               error("unknown packet type `%s'", optarg);
+                       break;
+
+               case 'v':
+                       ++vflag;
+                       break;
+
+               case 'w':
+                       WFileName = optarg;
+                       break;
+#ifdef YYDEBUG
+               case 'Y':
+                       {
+                       /* Undocumented flag */
+                       extern int yydebug;
+                       yydebug = 1;
+                       }
+                       break;
+#endif
+               case 'x':
+                       ++xflag;
+                       break;
+
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+
+       if (tflag > 0)
+               thiszone = gmt2local();
+
+       if (RFileName != NULL) {
+               /*
+                * We don't need network access, so set it back to the user id.
+                * Also, this prevents the user from reading anyone's
+                * trace file.
+                */
+               setuid(getuid());
+
+               pd = pcap_open_offline(RFileName, ebuf);
+               if (pd == NULL)
+                       error("%s", ebuf);
+               localnet = 0;
+               netmask = 0;
+               if (fflag != 0)
+                       error("-f and -r options are incompatible");
+       } else {
+               if (device == NULL) {
+                       device = pcap_lookupdev(ebuf);
+                       if (device == NULL)
+                               error("%s", ebuf);
+               }
+               pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
+               if (pd == NULL)
+                       error("%s", ebuf);
+               i = pcap_snapshot(pd);
+               if (snaplen < i) {
+                       warning("snaplen raised from %d to %d", snaplen, i);
+                       snaplen = i;
+               }
+               if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0)
+                       error("%s", ebuf);
+               /*
+                * Let user own process after socket has been opened.
+                */
+               setuid(getuid());
+       }
+       if (infile)
+               cmdbuf = read_infile(infile);
+       else
+               cmdbuf = copy_argv(&argv[optind]);
+
+       if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
+               error("%s", pcap_geterr(pd));
+       if (dflag) {
+               bpf_dump(&fcode, dflag);
+               exit(0);
+       }
+       init_addrtoname(fflag, localnet, netmask);
+
+       (void)signal(SIGTERM, cleanup);
+       (void)signal(SIGINT, cleanup);
+       (void)signal(SIGHUP, cleanup);
+
+       if (pcap_setfilter(pd, &fcode) < 0)
+               error("%s", pcap_geterr(pd));
+       if (WFileName) {
+               pcap_dumper_t *p = pcap_dump_open(pd, WFileName);
+               if (p == NULL)
+                       error("%s", pcap_geterr(pd));
+               printer = pcap_dump;
+               pcap_userdata = (u_char *)p;
+       } else {
+               printer = lookup_printer(pcap_datalink(pd));
+               pcap_userdata = 0;
+       }
+       if (RFileName == NULL) {
+               (void)fprintf(stderr, "%s: listening on %s\n",
+                   program_name, device);
+               (void)fflush(stderr);
+       }
+       if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
+               (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+                   program_name, pcap_geterr(pd));
+               exit(1);
+       }
+       pcap_close(pd);
+       exit(0);
+}
+
+/* make a clean exit on interrupts */
+RETSIGTYPE
+cleanup(int signo)
+{
+       struct pcap_stat stat;
+
+       /* Can't print the summary if reading from a savefile */
+       if (pd != NULL && pcap_file(pd) == NULL) {
+               (void)fflush(stdout);
+               putc('\n', stderr);
+               if (pcap_stats(pd, &stat) < 0)
+                       (void)fprintf(stderr, "pcap_stats: %s\n",
+                           pcap_geterr(pd));
+               else {
+                       (void)fprintf(stderr, "%d packets received by filter\n",
+                           stat.ps_recv);
+                       (void)fprintf(stderr, "%d packets dropped by kernel\n",
+                           stat.ps_drop);
+               }
+       }
+       exit(0);
+}
+
+/* Like default_print() but data need not be aligned */
+void
+default_print_unaligned(register const u_char *cp, register u_int length)
+{
+       register u_int i, s;
+       register int nshorts;
+
+       nshorts = (u_int) length / sizeof(u_short);
+       i = 0;
+       while (--nshorts >= 0) {
+               if ((i++ % 8) == 0)
+                       (void)printf("\n\t\t\t");
+               s = *cp++;
+               (void)printf(" %02x%02x", s, *cp++);
+       }
+       if (length & 1) {
+               if ((i % 8) == 0)
+                       (void)printf("\n\t\t\t");
+               (void)printf(" %02x", *cp);
+       }
+}
+
+void
+default_print(register const u_char *bp, register u_int length)
+{
+       register const u_short *sp;
+       register u_int i;
+       register int nshorts;
+
+       if ((long)bp & 1) {
+               default_print_unaligned(bp, length);
+               return;
+       }
+       sp = (u_short *)bp;
+       nshorts = (u_int) length / sizeof(u_short);
+       i = 0;
+       while (--nshorts >= 0) {
+               if ((i++ % 8) == 0)
+                       (void)printf("\n\t\t\t");
+               (void)printf(" %04x", ntohs(*sp++));
+       }
+       if (length & 1) {
+               if ((i % 8) == 0)
+                       (void)printf("\n\t\t\t");
+               (void)printf(" %02x", *(u_char *)sp);
+       }
+}
+
+__dead void
+usage(void)
+{
+       extern char version[];
+
+       (void)fprintf(stderr, "Version %s\n", version);
+       (void)fprintf(stderr,
+"Usage: tcpdump [-deflnNOpqStvx] [-c count] [ -F file ]\n");
+       (void)fprintf(stderr,
+"\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n");
+       (void)fprintf(stderr,
+"\t\t[ -T type ] [ -w file ] [ expression ]\n");
+       exit(-1);
+}
diff --git a/tcpdump.tproj/util.c b/tcpdump.tproj/util.c
new file mode 100644 (file)
index 0000000..6df0352
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/util.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <pcap.h>
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#include <unistd.h>
+
+#include "interface.h"
+
+/*
+ * Print out a filename (or other ascii string).
+ * If ep is NULL, assume no truncation check is needed.
+ * Return true if truncated.
+ */
+int
+fn_print(register const u_char *s, register const u_char *ep)
+{
+       register int ret;
+       register u_char c;
+
+       ret = 1;                        /* assume truncated */
+       while (ep == NULL || s < ep) {
+               c = *s++;
+               if (c == '\0') {
+                       ret = 0;
+                       break;
+               }
+               if (!isascii(c)) {
+                       c = toascii(c);
+                       putchar('M');
+                       putchar('-');
+               }
+               if (!isprint(c)) {
+                       c ^= 0x40;      /* DEL to ?, others to alpha */
+                       putchar('^');
+               }
+               putchar(c);
+       }
+       return(ret);
+}
+
+/*
+ * Print out a counted filename (or other ascii string).
+ * If ep is NULL, assume no truncation check is needed.
+ * Return true if truncated.
+ */
+int
+fn_printn(register const u_char *s, register u_int n,
+         register const u_char *ep)
+{
+       register int ret;
+       register u_char c;
+
+       ret = 1;                        /* assume truncated */
+       while (ep == NULL || s < ep) {
+               if (n-- <= 0) {
+                       ret = 0;
+                       break;
+               }
+               c = *s++;
+               if (!isascii(c)) {
+                       c = toascii(c);
+                       putchar('M');
+                       putchar('-');
+               }
+               if (!isprint(c)) {
+                       c ^= 0x40;      /* DEL to ?, others to alpha */
+                       putchar('^');
+               }
+               putchar(c);
+       }
+       return(ret);
+}
+
+/*
+ * Print the timestamp
+ */
+void
+ts_print(register const struct timeval *tvp)
+{
+       register int s;
+
+       if (tflag > 0) {
+               /* Default */
+               s = (tvp->tv_sec + thiszone) % 86400;
+               (void)printf("%02d:%02d:%02d.%06u ",
+                   s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
+       } else if (tflag < 0) {
+               /* Unix timeval style */
+               (void)printf("%u.%06u ",
+                   (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec);
+       }
+}
+
+/*
+ * Convert a token value to a string; use "fmt" if not found.
+ */
+const char *
+tok2str(register const struct tok *lp, register const char *fmt,
+       register int v)
+{
+       static char buf[128];
+
+       while (lp->s != NULL) {
+               if (lp->v == v)
+                       return (lp->s);
+               ++lp;
+       }
+       if (fmt == NULL)
+               fmt = "#%d";
+       (void)sprintf(buf, fmt, v);
+       return (buf);
+}
+
+
+/* VARARGS */
+__dead void
+#if __STDC__
+error(const char *fmt, ...)
+#else
+error(fmt, va_alist)
+       const char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: ", program_name);
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+       exit(1);
+       /* NOTREACHED */
+}
+
+/* VARARGS */
+void
+#if __STDC__
+warning(const char *fmt, ...)
+#else
+warning(fmt, va_alist)
+       const char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+       (void)fprintf(stderr, "%s: WARNING: ", program_name);
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       if (*fmt) {
+               fmt += strlen(fmt);
+               if (fmt[-1] != '\n')
+                       (void)fputc('\n', stderr);
+       }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+char *
+copy_argv(register char **argv)
+{
+       register char **p;
+       register u_int len = 0;
+       char *buf;
+       char *src, *dst;
+
+       p = argv;
+       if (*p == 0)
+               return 0;
+
+       while (*p)
+               len += strlen(*p++) + 1;
+
+       buf = (char *)malloc(len);
+       if (buf == NULL)
+               error("copy_argv: malloc");
+
+       p = argv;
+       dst = buf;
+       while ((src = *p++) != NULL) {
+               while ((*dst++ = *src++) != '\0')
+                       ;
+               dst[-1] = ' ';
+       }
+       dst[-1] = '\0';
+
+       return buf;
+}
+
+/* A replacement for strdup() that cuts down on malloc() overhead */
+char *
+savestr(register const char *str)
+{
+       register u_int size;
+       register char *p;
+       static char *strptr = NULL;
+       static u_int strsize = 0;
+
+       size = strlen(str) + 1;
+       if (size > strsize) {
+               strsize = 1024;
+               if (strsize < size)
+                       strsize = size;
+               strptr = (char *)malloc(strsize);
+               if (strptr == NULL)
+                       error("savestr: malloc");
+       }
+       (void)strcpy(strptr, str);
+       p = strptr;
+       strptr += size;
+       strsize -= size;
+       return (p);
+}
+
+char *
+read_infile(char *fname)
+{
+       register int fd, cc;
+       register char *cp;
+       struct stat buf;
+
+       fd = open(fname, O_RDONLY);
+       if (fd < 0)
+               error("can't open %s: %s", fname, pcap_strerror(errno));
+
+       if (fstat(fd, &buf) < 0)
+               error("can't stat %s: %s", fname, pcap_strerror(errno));
+
+       cp = malloc((u_int)buf.st_size + 1);
+       cc = read(fd, cp, (int)buf.st_size);
+       if (cc < 0)
+               error("read %s: %s", fname, pcap_strerror(errno));
+       if (cc != buf.st_size)
+               error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
+       cp[(int)buf.st_size] = '\0';
+
+       return (cp);
+}
+
+/*
+ * Returns the difference between gmt and local time in seconds.
+ * Use gmtime() and localtime() to keep things simple.
+ */
+int32_t
+gmt2local(void)
+{
+       register int dt, dir;
+       register struct tm *gmt, *loc;
+       time_t t;
+       struct tm sgmt;
+
+       t = time(NULL);
+       gmt = &sgmt;
+       *gmt = *gmtime(&t);
+       loc = localtime(&t);
+       dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
+           (loc->tm_min - gmt->tm_min) * 60;
+
+       /*
+        * If the year or julian day is different, we span 00:00 GMT
+        * and must add or subtract a day. Check the year first to
+        * avoid problems when the julian day wraps.
+        */
+       dir = loc->tm_year - gmt->tm_year;
+       if (dir == 0)
+               dir = loc->tm_yday - gmt->tm_yday;
+       dt += dir * 24 * 60 * 60;
+
+       return (dt);
+}
diff --git a/tcpdump.tproj/version.c b/tcpdump.tproj/version.c
new file mode 100644 (file)
index 0000000..2ee34ff
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: version.c,v 1.4 1996/07/13 11:01:35 mickey Exp $      */
+/*     $NetBSD: version.c,v 1.3 1996/05/20 00:41:20 fvdl Exp $ */
+
+char version[] = "3.2.0";
diff --git a/tcpdump.tproj/vfprintf.c b/tcpdump.tproj/vfprintf.c
new file mode 100644 (file)
index 0000000..3d5e80c
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+    "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/vfprintf.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "interface.h"
+
+#if 0
+
+/*
+ * Stock 4.3 doesn't have vfprintf.
+ * This routine is due to Chris Torek.
+ */
+vfprintf(f, fmt, args)
+       FILE *f;
+       char *fmt;
+       va_list args;
+{
+       int ret;
+
+       if ((f->_flag & _IOWRT) == 0) {
+               if (f->_flag & _IORW)
+                       f->_flag |= _IOWRT;
+               else
+                       return EOF;
+       }
+       ret = _doprnt(fmt, args, f);
+       return ferror(f) ? EOF : ret;
+}
+#endif /* 0 */
\ No newline at end of file
diff --git a/telnet.tproj/Makefile b/telnet.tproj/Makefile
new file mode 100644 (file)
index 0000000..0a096f6
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = telnet
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = externs.h fdset.h general.h krb4-proto.h ring.h types.h\
+         defines.h
+
+CFILES = authenc.c commands.c main.c network.c ring.c sys_bsd.c\
+         telnet.c terminal.c tn3270.c utilities.c
+
+OTHERSRCS = Makefile.preamble Makefile README telnet.1 Makefile.dist
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4
+WINDOWS_PB_CFLAGS = -DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4
+PDO_UNIX_PB_CFLAGS = -DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/telnet.tproj/Makefile.dist b/telnet.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..2e38a28
--- /dev/null
@@ -0,0 +1,73 @@
+#
+# Copyright (c) 1990 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#      @(#)Makefile    8.1 (Berkeley) 6/6/93
+#
+
+PROG=  telnet
+
+CFLAGS+=-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DAUTHENTICATION -DENCRYPTION
+CFLAGS+=-DENV_HACK
+CFLAGS+=-I${.CURDIR}/../../lib
+
+CFLAGS+= -DKRB4
+
+LDADD= -ltermcap -ltelnet
+LDADD+=        -lkrb -ldes
+DPADD= ${LIBTERMCAP}
+
+SRCS=  authenc.c commands.c main.c network.c ring.c sys_bsd.c telnet.c \
+       terminal.c tn3270.c utilities.c
+
+# These are the sources that have encryption stuff in them.
+CRYPT_SRC= authenc.c commands.c externs.h main.c network.c
+CRYPT_SRC+= ring.c ring.h telnet.c terminal.c utilities.c Makefile
+NOCRYPT_DIR=${.CURDIR}/Nocrypt
+
+.include <bsd.prog.mk>
+
+nocrypt:
+#ifdef ENCRYPTION
+       @for i in ${CRYPT_SRC}; do \
+           if [ ! -d ${NOCRYPT_DIR} ]; then \
+               echo Creating subdirectory ${NOCRYPT_DIR}; \
+               mkdir ${NOCRYPT_DIR}; \
+           fi; \
+           echo ${NOCRYPT_DIR}/$$i; \
+           unifdef -UENCRYPTION ${.CURDIR}/$$i | \
+               sed "s/ || defined(ENCRYPTION)//" > ${NOCRYPT_DIR}/$$i; \
+       done
+
+placeholder:
+#else  /* ENCRYPTION */
+       @echo "Encryption code already removed."
+#endif /* ENCRYPTION */
diff --git a/telnet.tproj/Makefile.preamble b/telnet.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..0f58055
--- /dev/null
@@ -0,0 +1,4 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+OTHER_LIBS = -ltelnet
+-include ../Makefile.include
diff --git a/telnet.tproj/PB.project b/telnet.tproj/PB.project
new file mode 100644 (file)
index 0000000..23bd9c5
--- /dev/null
@@ -0,0 +1,47 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (externs.h, fdset.h, general.h, "krb4-proto.h", ring.h, types.h, defines.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (
+            authenc.c, 
+            commands.c, 
+            main.c, 
+            network.c, 
+            ring.c, 
+            sys_bsd.c, 
+            telnet.c, 
+            terminal.c, 
+            tn3270.c, 
+            utilities.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, README, telnet.1, Makefile.dist); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4"; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4"; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = telnet; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = "-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4"; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/telnet.tproj/README b/telnet.tproj/README
new file mode 100644 (file)
index 0000000..37b588f
--- /dev/null
@@ -0,0 +1,743 @@
+
+This is a distribution of both client and server telnet.  These programs
+have been compiled on:
+                       telnet  telnetd
+       4.4 BSD-Lite      x       x
+       4.3 BSD Reno      X       X
+       UNICOS 9.1        X       X
+       UNICOS 9.0        X       X
+       UNICOS 8.0        X       X
+       BSDI 2.0          X       X
+       Solaris 2.4       x       x (no linemode in server)
+       SunOs 4.1.4       X       X (no linemode in server)
+       Ultrix 4.3        X       X (no linemode in server)
+       Ultrix 4.1        X       X (no linemode in server)
+
+In addition, previous versions have been compiled on the following
+machines, but were not available for testing this version.
+                       telnet  telnetd
+       Next1.0           X       X
+       UNICOS 8.3        X       X
+       UNICOS 7.C        X       X
+       UNICOS 7.0        X       X
+       SunOs 4.0.3c      X       X (no linemode in server)
+       4.3 BSD           X       X (no linemode in server)
+       DYNIX V3.0.12     X       X (no linemode in server)
+       Ultrix 3.1        X       X (no linemode in server)
+       Ultrix 4.0        X       X (no linemode in server)
+       SunOs 3.5         X       X (no linemode in server)
+       SunOs 4.1.3       X       X (no linemode in server)
+       Solaris 2.2       x       x (no linemode in server)
+       Solaris 2.3       x       x (no linemode in server)
+       BSDI 1.0          X       X
+       BSDI 1.1          X       X
+       DYNIX V3.0.17.9   X       X (no linemode in server)
+       HP-UX 8.0         x       x (no linemode in server)
+
+This code should work, but there are no guarantees.
+
+May 30, 1995
+
+This release represents what is on the 4.4BSD-Lite2 release, which
+should be the final BSD release.  I will continue to support of
+telnet, The code (without encryption) is available via anonymous ftp
+from ftp.cray.com, in src/telnet/telnet.YY.MM.DD.NE.tar.Z, where
+YY.MM.DD is replaced with the year, month and day of the release.
+If you can't find it at one of these places, at some point in the
+near future information about the latest releases should be available
+from ftp.borman.com.
+
+In addition, the version with the encryption code is available via
+ftp from net-dist.mit.edu, in the directory /pub/telnet.  There
+is a README file there that gives further information on how
+to get the distribution.
+
+Questions, comments, bug reports and bug fixes can be sent to
+one of these addresses:
+               dab@borman.com
+               dab@cray.com
+               dab@bsdi.com
+
+This release is mainly bug fixes and code cleanup.
+
+       Replace all calls to bcopy()/bzero() with calls to
+       memmove()/memset() and all calls to index()/rindex()
+       with calls to strchr()/strrchr().
+
+       Add some missing diagnostics for option tracing
+       to telnetd.
+
+       Add support for BSDI 2.0 and Solaris 2.4.
+
+       Add support for UNICOS 8.0
+
+       Get rid of expanded tabs and trailing white spaces.
+
+       From Paul Vixie:
+               Fix for telnet going into an endless spin
+               when the session dies abnormally.
+
+       From Jef Poskanzer:
+               Changes to allow telnet to compile
+               under SunOS 3.5.
+
+       From Philip Guenther:
+               makeutx() doesn't expand utmpx,
+               use pututxline() instead.
+
+       From Chris Torek:
+               Add a sleep(1) before execing login
+               to avoid race condition that can eat
+               up the login prompt.
+               Use terminal speed directly if it is
+               not an encoded value.
+
+       From Steve Parker:
+               Fix to realloc() call.  Fix for execing
+               login on solaris with no user name.
+
+January 19, 1994
+
+This is a list of some of the changes since the last tar release
+of telnet/telnetd.  There are probably other changes that aren't
+listed here, but this should hit a lot of the main ones.
+
+   General:
+       Changed #define for AUTHENTICATE to AUTHENTICATION
+       Changed #define for ENCRYPT to ENCRYPTION
+       Changed #define for DES_ENCRYPT to DES_ENCRYPTION
+
+       Added support for SPX authentication: -DSPX
+
+       Added support for Kerberos Version 5 authentication: -DKRB5
+
+       Added support for ANSI C function prototypes
+
+       Added support for the NEW-ENVIRON option (RFC-1572)
+       including support for USERVAR.
+
+       Made support for the old Environment Option (RFC-1408)
+       conditional on -DOLD_ENVIRON
+
+       Added #define ENV_HACK - support for RFC 1571
+
+       The encryption code is removed from the public distributions.
+       Domestic 4.4 BSD distributions contain the encryption code.
+
+       ENV_HACK: Code to deal with systems that only implement
+               the old ENVIRON option, and have reversed definitions
+               of ENV_VAR and ENV_VAL.  Also fixes ENV processing in
+               client to handle things besides just the default set...
+
+       NO_BSD_SETJMP: UNICOS configuration for
+               UNICOS 6.1/6.0/5.1/5.0 systems.
+
+       STREAMSPTY: Use /dev/ptmx to get a clean pty.  This
+               is for SVr4 derivatives (Like Solaris)
+
+       UTMPX: For systems that have /etc/utmpx. This is for
+               SVr4 derivatives (Like Solaris)
+
+       Definitions for BSDI 1.0
+
+       Definitions for 4.3 Reno and 4.4 BSD.
+
+       Definitions for UNICOS 8.0 and UNICOS 7.C
+
+       Definitions for Solaris 2.0
+
+       Definitions for HP-UX 8.0
+
+       Latest Copyright notices from Berkeley.
+
+       FLOW-CONTROL: support for RFC-XXXx
+
+
+   Client Specific:
+
+       Fix the "send" command to not send garbage...
+
+       Fix status message for "skiprc"
+
+       Make sure to send NAWS after telnet has been suspended
+       or an external command has been run, if the window size
+       has changed.
+
+       sysV88 support.
+
+   Server Specific:
+
+       Support flowcontrol option in non-linemode servers.
+
+       -k Server supports Kludge Linemode, but will default to
+          either single character mode or real Linemode support.
+          The user will have to explicitly ask to switch into
+          kludge linemode. ("stty extproc", or escape back to
+          to telnet and say "mode line".)
+
+       -u Specify the length of the hostname field in the utmp
+          file.  Hostname longer than this length will be put
+          into the utmp file in dotted decimal notation, rather
+          than putting in a truncated hostname.
+       
+       -U Registered hosts only.  If a reverse hostname lookup
+          fails, the connection will be refused.
+
+       -f/-F
+          Allows forwarding of credentials for KRB5.
+
+Februrary 22, 1991:
+
+    Features:
+
+       This version of telnet/telnetd has support for both
+       the AUTHENTICATION and ENCRYPTION options.  The
+       AUTHENTICATION option is fairly well defined, and
+       an option number has been assigned to it.  The
+       ENCRYPTION option is still in a state of flux; an
+       option number has been assigned to, but it is still
+       subject to change.  The code is provided in this release
+       for experimental and testing purposes.
+
+       The telnet "send" command can now be used to send
+       do/dont/will/wont commands, with any telnet option
+       name.  The rules for when do/dont/will/wont are sent
+       are still followed, so just because the user requests
+       that one of these be sent doesn't mean that it will
+       be sent...
+
+       The telnet "getstatus" command no longer requires
+       that option printing be enabled to see the response
+       to the "DO STATUS" command.
+
+       A -n flag has been added to telnetd to disable
+       keepalives.
+
+       A new telnet command, "auth" has been added (if
+       AUTHENTICATE is defined).  It has four sub-commands,
+       "status", "disable", "enable" and "help".
+
+       A new telnet command, "encrypt" has been added (if
+       ENCRYPT is defined).  It has many sub-commands:
+       "enable", "type", "start", "stop", "input",
+       "-input", "output", "-output", "status", and "help".
+
+       The LOGOUT option is now supported by both telnet
+       and telnetd, a new command, "logout", was added
+       to support this.
+
+       Several new toggle options were added:
+           "autoencrypt", "autodecrypt", "autologin", "authdebug",
+           "encdebug", "skiprc", "verbose_encrypt"
+
+       An "rlogin" interface has been added.  If the program
+       is named "rlogin", or the "-r" flag is given, then
+       an rlogin type of interface will be used.
+               ~.      Terminates the session
+               ~<susp> Suspend the session
+               ~^]     Escape to telnet command mode
+               ~~      Pass through the ~.
+           BUG: If you type the rlogin escape character
+                in the middle of a line while in rlogin
+                mode, you cannot erase it or any characters
+                before it.  Hopefully this can be fixed
+                in a future release...
+
+    General changes:
+
+       A "libtelnet.a" has now been created.  This libraray
+       contains code that is common to both telnet and
+       telnetd.  This is also where library routines that
+       are needed, but are not in the standard C library,
+       are placed.
+
+       The makefiles have been re-done.  All of the site
+       specific configuration information has now been put
+       into a single "Config.generic" file, in the top level
+       directory.  Changing this one file will take care of
+       all three subdirectories.  Also, to add a new/local
+       definition, a "Config.local" file may be created
+       at the top level; if that file exists, the subdirectories
+       will use that file instead of "Config.generic".
+
+       Many 1-2 line functions in commands.c have been
+       removed, and just inserted in-line, or replaced
+       with a macro.
+
+    Bug Fixes:
+
+       The non-termio code in both telnet and telnetd was
+       setting/clearing CTLECH in the sg_flags word.  This
+       was incorrect, and has been changed to set/clear the
+       LCTLECH bit in the local mode word.
+
+       The SRCRT #define has been removed.  If IP_OPTIONS
+       and IPPROTO_IP are defined on the system, then the
+       source route code is automatically enabled.
+
+       The NO_GETTYTAB #define has been removed; there
+       is a compatability routine that can be built into
+       libtelnet to achive the same results.
+
+       The server, telnetd, has been switched to use getopt()
+       for parsing the argument list.
+
+       The code for getting the input/output speeds via
+       cfgetispeed()/cfgetospeed() was still not quite
+       right in telnet.  Posix says if the ispeed is 0,
+       then it is really equal to the ospeed.
+
+       The suboption processing code in telnet now has
+       explicit checks to make sure that we received
+       the entire suboption (telnetd was already doing this).
+
+       The telnet code for processing the terminal type
+       could cause a core dump if an existing connection
+       was closed, and a new connection opened without
+       exiting telnet.
+
+       Telnetd was doing a TCSADRAIN when setting the new
+       terminal settings;  This is not good, because it means
+       that the tcsetattr() will hang waiting for output to
+       drain, and telnetd is the only one that will drain
+       the output...  The fix is to use TCSANOW which does
+       not wait.
+
+       Telnetd was improperly setting/clearing the ISTRIP
+       flag in the c_lflag field, it should be using the
+       c_iflag field. 
+
+       When the child process of telnetd was opening the
+       slave side of the pty, it was re-setting the EXTPROC
+       bit too early, and some of the other initialization
+       code was wiping it out.  This would cause telnetd
+       to go out of linemode and into single character mode.
+
+       One instance of leaving linemode in telnetd forgot
+       to send a WILL ECHO to the client, the net result
+       would be that the user would see double character
+       echo.
+
+       If the MODE was being changed several times very
+       quickly, telnetd could get out of sync with the
+       state changes and the returning acks; and wind up
+       being left in the wrong state.
+
+September 14, 1990:
+
+       Switch the client to use getopt() for parsing the
+       argument list.  The 4.3Reno getopt.c is included for
+       systems that don't have getopt().
+
+       Use the posix _POSIX_VDISABLE value for what value
+       to use when disabling special characters.  If this
+       is undefined, it defaults to 0x3ff.
+
+       For non-termio systems, TIOCSETP was being used to
+       change the state of the terminal.  This causes the
+       input queue to be flushed, which we don't want.  This
+       is now changed to TIOCSETN.
+
+       Take out the "#ifdef notdef" around the code in the
+       server that generates a "sync" when the pty oputput
+       is flushed.  The potential problem is that some older
+       telnet clients may go into an infinate loop when they
+       receive a "sync", if so, the server can be compiled
+       with "NO_URGENT" defined.
+
+       Fix the client where it was setting/clearing the OPOST
+       bit in the c_lflag field, not the c_oflag field.
+
+       Fix the client where it was setting/clearing the ISTRIP
+       bit in the c_lflag field, not the c_iflag field.  (On
+       4.3Reno, this is the ECHOPRT bit in the c_lflag field.)
+       The client also had its interpretation of WILL BINARY
+       and DO BINARY reversed.
+
+       Fix a bug in client that would cause a core dump when
+       attempting to remove the last environment variable.
+
+       In the client, there were a few places were switch()
+       was being passed a character, and if it was a negative
+       value, it could get sign extended, and not match
+       the 8 bit case statements.  The fix is to and the
+       switch value with 0xff.
+
+       Add a couple more printoption() calls in the client, I
+       don't think there are any more places were a telnet
+       command can be received and not printed out when
+       "options" is on.
+
+       A new flag has been added to the client, "-a".  Currently,
+       this just causes the USER name to be sent across, in
+       the future this may be used to signify that automatic
+       authentication is requested.
+
+       The USER variable is now only sent by the client if
+       the "-a" or "-l user" options are explicity used, or
+       if the user explicitly asks for the "USER" environment
+       variable to be exported.  In the server, if it receives
+       the "USER" environment variable, it won't print out the
+       banner message, so that only "Password:" will be printed.
+       This makes the symantics more like rlogin, and should be
+       more familiar to the user.  (People are not used to
+       getting a banner message, and then getting just a
+       "Password:" prompt.)
+
+       Re-vamp the code for starting up the child login
+       process.  The code was getting ugly, and it was
+       hard to tell what was really going on.  What we
+       do now is after the fork(), in the child:
+               1) make sure we have no controlling tty
+               2) open and initialize the tty
+               3) do a setsid()/setpgrp()
+               4) makes the tty our controlling tty.
+       On some systems, #2 makes the tty our controlling
+       tty, and #4 is a no-op.  The parent process does
+       a gets rid of any controlling tty after the child
+       is fork()ed.
+
+       Use the strdup() library routine in telnet, instead
+       of the local savestr() routine.  If you don't have
+       strdup(), you need to define NO_STRDUP.
+
+       Add support for ^T (SIGINFO/VSTATUS), found in the
+       4.3Reno distribution.  This maps to the AYT character.
+       You need a 4-line bugfix in the kernel to get this
+       to work properly:
+
+       > *** tty_pty.c.ORG     Tue Sep 11 09:41:53 1990
+       > --- tty_pty.c Tue Sep 11 17:48:03 1990
+       > ***************
+       > *** 609,613 ****
+       >                       if ((tp->t_lflag&NOFLSH) == 0)
+       >                               ttyflush(tp, FREAD|FWRITE);
+       > !                     pgsignal(tp->t_pgrp, *(unsigned int *)data);
+       >                       return(0);
+       >               }
+       > --- 609,616 ----
+       >                       if ((tp->t_lflag&NOFLSH) == 0)
+       >                               ttyflush(tp, FREAD|FWRITE);
+       > !                     pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
+       > !                     if ((*(unsigned int *)data == SIGINFO) &&
+       > !                         ((tp->t_lflag&NOKERNINFO) == 0))
+       > !                             ttyinfo(tp);
+       >                       return(0);
+       >               }
+
+       The client is now smarter when setting the telnet escape
+       character; it only sets it to one of VEOL and VEOL2 if
+       one of them is undefined, and the other one is not already
+       defined to the telnet escape character.
+
+       Handle TERMIOS systems that have seperate input and output
+       line speed settings imbedded in the flags.
+
+       Many other minor bug fixes.
+
+June 20, 1990:
+       Re-organize makefiles and source tree.  The telnet/Source
+       directory is now gone, and all the source that was in
+       telnet/Source is now just in the telnet directory.
+
+       Seperate makefile for each system are now gone.  There
+       are two makefiles, Makefile and Makefile.generic.
+       The "Makefile" has the definitions for the various
+       system, and "Makefile.generic" does all the work.
+       There is a variable called "WHAT" that is used to
+       specify what to make.  For example, in the telnet
+       directory, you might say:
+               make 4.4bsd WHAT=clean
+       to clean out the directory.
+
+       Add support for the ENVIRON and XDISPLOC options.
+       In order for the server to work, login has to have
+       the "-p" option to preserve environment variables.
+
+       Add the SOFT_TAB and LIT_ECHO modes in the LINEMODE support.
+
+       Add the "-l user" option to command line and open command
+       (This is passed through the ENVIRON option).
+
+       Add the "-e" command line option, for setting the escape
+       character.
+
+       Add the "-D", diagnostic, option to the server.  This allows
+       the server to print out debug information, which is very
+       useful when trying to debug a telnet that doesn't have any
+       debugging ability.
+
+       Turn off the literal next character when not in LINEMODE.
+
+       Don't recognize ^Y locally, just pass it through.
+
+       Make minor modifications for Sun4.0 and Sun4.1
+
+       Add support for both FORW1 and FORW2 characters.  The
+       telnet escpape character is set to whichever of the
+       two is not being used.  If both are in use, the escape
+       character is not set, so when in linemode the user will
+       have to follow the escape character with a <CR> or <EOF)
+       to get it passed through.
+
+       Commands can now be put in single and double quotes, and
+       a backslash is now an escape character.  This is needed
+       for allowing arbitrary strings to be assigned to environment
+       variables.
+
+       Switch telnetd to use macros like telnet for keeping
+       track of the state of all the options.
+
+       Fix telnetd's processing of options so that we always do
+       the right processing of the LINEMODE option, regardless
+       of who initiates the request to turn it on.  Also, make
+       sure that if the other side went "WILL ECHO" in response
+       to our "DO ECHO", that we send a "DONT ECHO" to get the
+       option turned back off!
+
+       Fix the TERMIOS setting of the terminal speed to handle both
+       BSD's seperate fields, and the SYSV method of CBAUD bits.
+
+       Change how we deal with the other side refusing to enable
+       an option.  The sequence used to be: send DO option; receive
+       WONT option; send DONT option.  Now, the sequence is: send
+       DO option; receive WONT option.  Both should be valid
+       according to the spec, but there has been at least one
+       client implementation of telnet identified that can get
+       really confused by this.  (The exact sequence, from a trace
+       on the server side, is (numbers are number of responses that
+       we expect to get after that line...):
+
+               send WILL ECHO  1 (initial request)
+               send WONT ECHO  2 (server is changing state)
+               recv DO ECHO    1 (first reply, ok.  expect DONT ECHO next)
+               send WILL ECHO  2 (server changes state again)
+               recv DONT ECHO  1 (second reply, ok.  expect DO ECHO next)
+               recv DONT ECHO  0 (third reply, wrong answer. got DONT!!!)
+       ***     send WONT ECHO    (send WONT to acknowledge the DONT)
+               send WILL ECHO  1 (ask again to enable option)
+               recv DO ECHO    0
+
+               recv DONT ECHO  0
+               send WONT ECHO  1
+               recv DONT ECHO  0
+               recv DO ECHO    1
+               send WILL ECHO  0
+               (and the last 5 lines loop forever)
+
+       The line with the "***" is last of the WILL/DONT/WONT sequence.
+       The change to the server to not generate that makes this same
+       example become:
+
+               send will ECHO  1
+               send wont ECHO  2
+               recv do ECHO    1
+               send will ECHO  2
+               recv dont ECHO  1
+               recv dont ECHO  0
+               recv do ECHO    1
+               send will ECHO  0
+
+       There is other option negotiation going on, and not sending
+       the third part changes some of the timings, but this specific
+       example no longer gets stuck in a loop.  The "telnet.state"
+       file has been modified to reflect this change to the algorithm.
+
+       A bunch of miscellaneous bug fixes and changes to make
+       lint happier.
+
+       This version of telnet also has some KERBEROS stuff in
+       it. This has not been tested, it uses an un-authorized
+       telnet option number, and uses an out-of-date version
+       of the (still being defined) AUTHENTICATION option.
+       There is no support for this code, do not enable it.
+
+
+March 1, 1990:
+CHANGES/BUGFIXES SINCE LAST RELEASE:
+       Some support for IP TOS has been added.  Requires that the
+       kernel support the IP_TOS socket option (currently this
+       is only in UNICOS 6.0).
+
+       Both telnet and telnetd now use the cc_t typedef.  typedefs are
+       included for systems that don't have it (in termios.h).
+
+       SLC_SUSP was not supported properly before.  It is now.
+
+       IAC EOF was not translated  properly in telnetd for SYSV_TERMIO
+       when not in linemode.  It now saves a copy of the VEOF character,
+       so that when ICANON is turned off and we can't trust it anymore
+       (because it is now the VMIN character) we use the saved value.
+
+       There were two missing "break" commands in the linemode
+       processing code in telnetd.
+
+       Telnetd wasn't setting the kernel window size information
+       properly.  It was using the rows for both rows and columns...
+
+Questions/comments go to
+               David Borman
+               Cray Research, Inc.
+               655F Lone Oak Drive
+               Eagan, MN 55123
+               dab@cray.com.
+
+README:        You are reading it.
+
+Config.generic:
+       This file contains all the OS specific definitions.  It
+       has pre-definitions for many common system types, and is
+       in standard makefile fromat.  See the comments at the top
+       of the file for more information.
+
+Config.local:
+       This is not part of the distribution, but if this file exists,
+       it is used instead of "Config.generic".  This allows site
+       specific configuration without having to modify the distributed
+       "Config.generic" file.
+
+kern.diff:
+       This file contains the diffs for the changes needed for the
+       kernel to support LINEMODE is the server.  These changes are
+       for a 4.3BSD system.  You may need to make some changes for
+       your particular system.
+
+       There is a new bit in the terminal state word, TS_EXTPROC.
+       When this bit is set, several aspects of the terminal driver
+       are disabled.  Input line editing, character echo, and
+       mapping of signals are all disabled.  This allows the telnetd
+       to turn of these functions when in linemode, but still keep
+       track of what state the user wants the terminal to be in.
+
+       New ioctl()s:
+
+               TIOCEXT         Turn on/off the TS_EXTPROC bit
+               TIOCGSTATE      Get t_state of tty to look at TS_EXTPROC bit
+               TIOCSIG         Generate a signal to processes in the
+                               current process group of the pty.
+
+       There is a new mode for packet driver, the TIOCPKT_IOCTL bit.
+       When packet mode is turned on in the pty, and the TS_EXTPROC
+       bit is set, then whenever the state of the pty is changed, the
+       next read on the master side of the pty will have the TIOCPKT_IOCTL
+       bit set, and the data will contain the following:
+               struct xx {
+                       struct sgttyb a;
+                       struct tchars b;
+                       struct ltchars c;
+                       int t_state;
+                       int t_flags;
+               }
+       This allows the process on the server side of the pty to know
+       when the state of the terminal has changed, and what the new
+       state is.
+
+       However, if you define USE_TERMIO or SYSV_TERMIO, the code will
+       expect that the structure returned in the TIOCPKT_IOCTL is
+       the termio/termios structure.
+
+stty.diff:
+       This file contains the changes needed for the stty(1) program
+       to report on the current status of the TS_EXTPROC bit.  It also
+       allows the user to turn on/off the TS_EXTPROC bit.  This is useful
+       because it allows the user to say "stty -extproc", and the
+       LINEMODE option will be automatically disabled, and saying "stty
+       extproc" will re-enable the LINEMODE option.
+
+telnet.state:
+       Both the client and server have code in them to deal
+       with option negotiation loops.  The algorithm that is
+       used is described in this file.
+
+telnet:
+       This directory contains the client code.  No kernel changes are
+       needed to use this code.
+
+telnetd:
+       This directory contains the server code.  If LINEMODE or KLUDGELINEMODE
+       are defined, then the kernel modifications listed above are needed.
+
+libtelnet:
+       This directory contains code that is common to both the client
+       and the server.
+
+arpa:
+       This directory has a new <arpa/telnet.h>
+
+libtelnet/Makefile.4.4:
+telnet/Makefile.4.4:
+telnetd/Makefile.4.4:
+       These are the makefiles that can be used on a 4.3Reno
+       system when this software is installed in /usr/src/lib/libtelnet,
+       /usr/src/libexec/telnetd, and /usr/src/usr.bin/telnet.
+
+
+The following TELNET options are supported:
+       
+       LINEMODE:
+               The LINEMODE option is supported as per RFC1116.  The
+               FORWARDMASK option is not currently supported.
+
+       BINARY: The client has the ability to turn on/off the BINARY
+               option in each direction.  Turning on BINARY from
+               server to client causes the LITOUT bit to get set in
+               the terminal driver on both ends,  turning on BINARY
+               from the client to the server causes the PASS8 bit
+               to get set in the terminal driver on both ends.
+
+       TERMINAL-TYPE:
+               This is supported as per RFC1091.  On the server side,
+               when a terminal type is received, termcap/terminfo
+               is consulted to determine if it is a known terminal
+               type.  It keeps requesting terminal types until it
+               gets one that it recongnizes, or hits the end of the
+               list.  The server side looks up the entry in the
+               termcap/terminfo data base, and generates a list of
+               names which it then passes one at a time to each
+               request for a terminal type, duplicating the last
+               entry in the list before cycling back to the beginning.
+
+       NAWS:   The Negotiate about Window Size, as per RFC 1073.
+
+       TERMINAL-SPEED:
+               Implemented as per RFC 1079
+
+       TOGGLE-FLOW-CONTROL:
+               Implemented as per RFC 1080
+
+       TIMING-MARK:
+               As per RFC 860
+
+       SGA:    As per RFC 858
+
+       ECHO:   As per RFC 857
+
+       LOGOUT: As per RFC 727
+
+       STATUS:
+               The server will send its current status upon
+               request.  It does not ask for the clients status.
+               The client will request the servers current status
+               from the "send getstatus" command.
+
+       ENVIRON:
+               This option is currently being defined by the IETF
+               Telnet Working Group, and an RFC has not yet been
+               issued, but should be in the near future...
+
+       X-DISPLAY-LOCATION:
+               This functionality can be done through the ENVIRON
+               option, it is added here for completeness.
+
+       AUTHENTICATION:
+               This option is currently being defined by the IETF
+               Telnet Working Group, and an RFC has not yet been
+               issued.  The basic framework is pretty much decided,
+               but the definitions for the specific authentication
+               schemes is still in a state of flux.
+
+       ENCRYPTION:
+               This option is currently being defined by the IETF
+               Telnet Working Group, and an RFC has not yet been
+               issued.  The draft RFC is still in a state of flux,
+               so this code may change in the future.
diff --git a/telnet.tproj/authenc.c b/telnet.tproj/authenc.c
new file mode 100644 (file)
index 0000000..9d5330d
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)authenc.c  8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#if    defined(AUTHENTICATION) || defined(ENCRYPTION)
+#include <sys/types.h>
+#include <arpa/telnet.h>
+#include <libtelnet/encrypt.h>
+#include <libtelnet/misc.h>
+
+#include "general.h"
+#include "ring.h"
+#include "externs.h"
+#include "defines.h"
+#include "types.h"
+
+       int
+net_write(str, len)
+       unsigned char *str;
+       int len;
+{
+       if (NETROOM() > len) {
+               ring_supply_data(&netoring, str, len);
+               if (str[0] == IAC && str[1] == SE)
+                       printsub('>', &str[2], len-2);
+               return(len);
+       }
+       return(0);
+}
+
+       void
+net_encrypt()
+{
+#ifdef ENCRYPTION
+       if (encrypt_output)
+               ring_encrypt(&netoring, encrypt_output);
+       else
+               ring_clearto(&netoring);
+#endif /* ENCRYPTION */
+}
+
+       int
+telnet_spin()
+{
+       return(-1);
+}
+
+       char *
+telnet_getenv(val)
+       char *val;
+{
+       return((char *)env_getvalue((unsigned char *)val));
+}
+
+       char *
+telnet_gets(prompt, result, length, echo)
+       char *prompt;
+       char *result;
+       int length;
+       int echo;
+{
+       extern char *getpass();
+       extern int globalmode;
+       int om = globalmode;
+       char *res;
+
+       TerminalNewMode(-1);
+       if (echo) {
+               printf("%s", prompt);
+               res = fgets(result, length, stdin);
+       } else if (res = getpass(prompt)) {
+               strncpy(result, res, length);
+               res = result;
+       }
+       TerminalNewMode(om);
+       return(res);
+}
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
diff --git a/telnet.tproj/commands.c b/telnet.tproj/commands.c
new file mode 100644 (file)
index 0000000..903bda3
--- /dev/null
@@ -0,0 +1,2990 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#if    defined(unix) || defined(__APPLE__)
+#include <sys/param.h>
+#if    defined(CRAY) || defined(sysV88)
+#include <sys/types.h>
+#endif
+#include <sys/file.h>
+#else
+#include <sys/types.h>
+#endif /* defined(unix) || defined(__APPLE__) */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef CRAY
+#include <fcntl.h>
+#endif /* CRAY */
+
+#include <signal.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <pwd.h>
+#if !defined(__APPLE__)
+#include <varargs.h>
+#endif
+#include <errno.h>
+
+#include <arpa/telnet.h>
+
+#include "general.h"
+
+#include "ring.h"
+
+#include "externs.h"
+#include "defines.h"
+#include "types.h"
+
+#if !defined(CRAY) && !defined(sysV88)
+#include <netinet/in_systm.h>
+# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
+# include <machine/endian.h>
+# endif /* vax */
+#endif /* !defined(CRAY) && !defined(sysV88) */
+#include <netinet/ip.h>
+
+
+#ifndef        MAXHOSTNAMELEN
+#define        MAXHOSTNAMELEN 64
+#endif MAXHOSTNAMELEN
+
+#if    defined(IPPROTO_IP) && defined(IP_TOS)
+int tos = -1;
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+char   *hostname;
+static char _hostname[MAXHOSTNAMELEN];
+
+extern char *getenv();
+
+extern int isprefix();
+extern char **genget();
+extern int Ambiguous();
+
+typedef int (*intrtn_t)();
+#if __STDC__
+static call(intrtn_t routine, ...);
+#else
+static call();
+#endif
+
+typedef struct {
+       char    *name;          /* command name */
+       char    *help;          /* help string (NULL for no help) */
+       int     (*handler)();   /* routine which executes command */
+       int     needconnect;    /* Do we need to be connected to execute? */
+} Command;
+
+static char line[256];
+static char saveline[256];
+static int margc;
+static char *margv[20];
+
+    static void
+makeargv()
+{
+    register char *cp, *cp2, c;
+    register char **argp = margv;
+
+    margc = 0;
+    cp = line;
+    if (*cp == '!') {          /* Special case shell escape */
+       strcpy(saveline, line); /* save for shell command */
+       *argp++ = "!";          /* No room in string to get this */
+       margc++;
+       cp++;
+    }
+    while (c = *cp) {
+       register int inquote = 0;
+       while (isspace(c))
+           c = *++cp;
+       if (c == '\0')
+           break;
+       *argp++ = cp;
+       margc += 1;
+       for (cp2 = cp; c != '\0'; c = *++cp) {
+           if (inquote) {
+               if (c == inquote) {
+                   inquote = 0;
+                   continue;
+               }
+           } else {
+               if (c == '\\') {
+                   if ((c = *++cp) == '\0')
+                       break;
+               } else if (c == '"') {
+                   inquote = '"';
+                   continue;
+               } else if (c == '\'') {
+                   inquote = '\'';
+                   continue;
+               } else if (isspace(c))
+                   break;
+           }
+           *cp2++ = c;
+       }
+       *cp2 = '\0';
+       if (c == '\0')
+           break;
+       cp++;
+    }
+    *argp++ = 0;
+}
+
+/*
+ * Make a character string into a number.
+ *
+ * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
+ */
+
+       static
+special(s)
+       register char *s;
+{
+       register char c;
+       char b;
+
+       switch (*s) {
+       case '^':
+               b = *++s;
+               if (b == '?') {
+                   c = b | 0x40;               /* DEL */
+               } else {
+                   c = b & 0x1f;
+               }
+               break;
+       default:
+               c = *s;
+               break;
+       }
+       return c;
+}
+
+/*
+ * Construct a control character sequence
+ * for a special character.
+ */
+       static char *
+control(c)
+       register cc_t c;
+{
+       static char buf[5];
+       /*
+        * The only way I could get the Sun 3.5 compiler
+        * to shut up about
+        *      if ((unsigned int)c >= 0x80)
+        * was to assign "c" to an unsigned int variable...
+        * Arggg....
+        */
+       register unsigned int uic = (unsigned int)c;
+
+       if (uic == 0x7f)
+               return ("^?");
+       if (c == (cc_t)_POSIX_VDISABLE) {
+               return "off";
+       }
+       if (uic >= 0x80) {
+               buf[0] = '\\';
+               buf[1] = ((c>>6)&07) + '0';
+               buf[2] = ((c>>3)&07) + '0';
+               buf[3] = (c&07) + '0';
+               buf[4] = 0;
+       } else if (uic >= 0x20) {
+               buf[0] = c;
+               buf[1] = 0;
+       } else {
+               buf[0] = '^';
+               buf[1] = '@'+c;
+               buf[2] = 0;
+       }
+       return (buf);
+}
+
+
+
+/*
+ *     The following are data structures and routines for
+ *     the "send" command.
+ *
+ */
+
+struct sendlist {
+    char       *name;          /* How user refers to it (case independent) */
+    char       *help;          /* Help information (0 ==> no help) */
+    int                needconnect;    /* Need to be connected */
+    int                narg;           /* Number of arguments */
+    int                (*handler)();   /* Routine to perform (for special ops) */
+    int                nbyte;          /* Number of bytes to send this command */
+    int                what;           /* Character to be sent (<0 ==> special) */
+};
+\f
+
+static int
+       send_esc P((void)),
+       send_help P((void)),
+       send_docmd P((char *)),
+       send_dontcmd P((char *)),
+       send_willcmd P((char *)),
+       send_wontcmd P((char *));
+
+static struct sendlist Sendlist[] = {
+    { "ao",    "Send Telnet Abort output",             1, 0, 0, 2, AO },
+    { "ayt",   "Send Telnet 'Are You There'",          1, 0, 0, 2, AYT },
+    { "brk",   "Send Telnet Break",                    1, 0, 0, 2, BREAK },
+    { "break", 0,                                      1, 0, 0, 2, BREAK },
+    { "ec",    "Send Telnet Erase Character",          1, 0, 0, 2, EC },
+    { "el",    "Send Telnet Erase Line",               1, 0, 0, 2, EL },
+    { "escape",        "Send current escape character",        1, 0, send_esc, 1, 0 },
+    { "ga",    "Send Telnet 'Go Ahead' sequence",      1, 0, 0, 2, GA },
+    { "ip",    "Send Telnet Interrupt Process",        1, 0, 0, 2, IP },
+    { "intp",  0,                                      1, 0, 0, 2, IP },
+    { "interrupt", 0,                                  1, 0, 0, 2, IP },
+    { "intr",  0,                                      1, 0, 0, 2, IP },
+    { "nop",   "Send Telnet 'No operation'",           1, 0, 0, 2, NOP },
+    { "eor",   "Send Telnet 'End of Record'",          1, 0, 0, 2, EOR },
+    { "abort", "Send Telnet 'Abort Process'",          1, 0, 0, 2, ABORT },
+    { "susp",  "Send Telnet 'Suspend Process'",        1, 0, 0, 2, SUSP },
+    { "eof",   "Send Telnet End of File Character",    1, 0, 0, 2, xEOF },
+    { "synch", "Perform Telnet 'Synch operation'",     1, 0, dosynch, 2, 0 },
+    { "getstatus", "Send request for STATUS",          1, 0, get_status, 6, 0 },
+    { "?",     "Display send options",                 0, 0, send_help, 0, 0 },
+    { "help",  0,                                      0, 0, send_help, 0, 0 },
+    { "do",    0,                                      0, 1, send_docmd, 3, 0 },
+    { "dont",  0,                                      0, 1, send_dontcmd, 3, 0 },
+    { "will",  0,                                      0, 1, send_willcmd, 3, 0 },
+    { "wont",  0,                                      0, 1, send_wontcmd, 3, 0 },
+    { 0 }
+};
+
+#define        GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
+                               sizeof(struct sendlist)))
+
+    static int
+sendcmd(argc, argv)
+    int  argc;
+    char **argv;
+{
+    int count;         /* how many bytes we are going to need to send */
+    int i;
+    int question = 0;  /* was at least one argument a question */
+    struct sendlist *s;        /* pointer to current command */
+    int success = 0;
+    int needconnect = 0;
+
+    if (argc < 2) {
+       printf("need at least one argument for 'send' command\n");
+       printf("'send ?' for help\n");
+       return 0;
+    }
+    /*
+     * First, validate all the send arguments.
+     * In addition, we see how much space we are going to need, and
+     * whether or not we will be doing a "SYNCH" operation (which
+     * flushes the network queue).
+     */
+    count = 0;
+    for (i = 1; i < argc; i++) {
+       s = GETSEND(argv[i]);
+       if (s == 0) {
+           printf("Unknown send argument '%s'\n'send ?' for help.\n",
+                       argv[i]);
+           return 0;
+       } else if (Ambiguous(s)) {
+           printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
+                       argv[i]);
+           return 0;
+       }
+       if (i + s->narg >= argc) {
+           fprintf(stderr,
+           "Need %d argument%s to 'send %s' command.  'send %s ?' for help.\n",
+               s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
+           return 0;
+       }
+       count += s->nbyte;
+       if (s->handler == send_help) {
+           send_help();
+           return 0;
+       }
+
+       i += s->narg;
+       needconnect += s->needconnect;
+    }
+    if (!connected && needconnect) {
+       printf("?Need to be connected first.\n");
+       printf("'send ?' for help\n");
+       return 0;
+    }
+    /* Now, do we have enough room? */
+    if (NETROOM() < count) {
+       printf("There is not enough room in the buffer TO the network\n");
+       printf("to process your request.  Nothing will be done.\n");
+       printf("('send synch' will throw away most data in the network\n");
+       printf("buffer, if this might help.)\n");
+       return 0;
+    }
+    /* OK, they are all OK, now go through again and actually send */
+    count = 0;
+    for (i = 1; i < argc; i++) {
+       if ((s = GETSEND(argv[i])) == 0) {
+           fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
+           (void) quit();
+           /*NOTREACHED*/
+       }
+       if (s->handler) {
+           count++;
+           success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
+                                 (s->narg > 1) ? argv[i+2] : 0);
+           i += s->narg;
+       } else {
+           NET2ADD(IAC, s->what);
+           printoption("SENT", IAC, s->what);
+       }
+    }
+    return (count == success);
+}
+
+    static int
+send_esc()
+{
+    NETADD(escape);
+    return 1;
+}
+
+    static int
+send_docmd(name)
+    char *name;
+{
+    return(send_tncmd(send_do, "do", name));
+}
+
+    static int
+send_dontcmd(name)
+    char *name;
+{
+    return(send_tncmd(send_dont, "dont", name));
+}
+    static int
+send_willcmd(name)
+    char *name;
+{
+    return(send_tncmd(send_will, "will", name));
+}
+    static int
+send_wontcmd(name)
+    char *name;
+{
+    return(send_tncmd(send_wont, "wont", name));
+}
+
+    int
+send_tncmd(func, cmd, name)
+    void       (*func)();
+    char       *cmd, *name;
+{
+    char **cpp;
+    extern char *telopts[];
+    register int val = 0;
+
+    if (isprefix(name, "help") || isprefix(name, "?")) {
+       register int col, len;
+
+       printf("Usage: send %s <value|option>\n", cmd);
+       printf("\"value\" must be from 0 to 255\n");
+       printf("Valid options are:\n\t");
+
+       col = 8;
+       for (cpp = telopts; *cpp; cpp++) {
+           len = strlen(*cpp) + 3;
+           if (col + len > 65) {
+               printf("\n\t");
+               col = 8;
+           }
+           printf(" \"%s\"", *cpp);
+           col += len;
+       }
+       printf("\n");
+       return 0;
+    }
+    cpp = (char **)genget(name, telopts, sizeof(char *));
+    if (Ambiguous(cpp)) {
+       fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
+                                       name, cmd);
+       return 0;
+    }
+    if (cpp) {
+       val = cpp - telopts;
+    } else {
+       register char *cp = name;
+
+       while (*cp >= '0' && *cp <= '9') {
+           val *= 10;
+           val += *cp - '0';
+           cp++;
+       }
+       if (*cp != 0) {
+           fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
+                                       name, cmd);
+           return 0;
+       } else if (val < 0 || val > 255) {
+           fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
+                                       name, cmd);
+           return 0;
+       }
+    }
+    if (!connected) {
+       printf("?Need to be connected first.\n");
+       return 0;
+    }
+    (*func)(val, 1);
+    return 1;
+}
+
+    static int
+send_help()
+{
+    struct sendlist *s;        /* pointer to current command */
+    for (s = Sendlist; s->name; s++) {
+       if (s->help)
+           printf("%-15s %s\n", s->name, s->help);
+    }
+    return(0);
+}
+\f
+/*
+ * The following are the routines and data structures referred
+ * to by the arguments to the "toggle" command.
+ */
+
+    static int
+lclchars()
+{
+    donelclchars = 1;
+    return 1;
+}
+
+    static int
+togdebug()
+{
+#ifndef        NOT43
+    if (net > 0 &&
+       (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
+           perror("setsockopt (SO_DEBUG)");
+    }
+#else  /* NOT43 */
+    if (debug) {
+       if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+           perror("setsockopt (SO_DEBUG)");
+    } else
+       printf("Cannot turn off socket debugging\n");
+#endif /* NOT43 */
+    return 1;
+}
+
+
+    static int
+togcrlf()
+{
+    if (crlf) {
+       printf("Will send carriage returns as telnet <CR><LF>.\n");
+    } else {
+       printf("Will send carriage returns as telnet <CR><NUL>.\n");
+    }
+    return 1;
+}
+
+int binmode;
+
+    static int
+togbinary(val)
+    int val;
+{
+    donebinarytoggle = 1;
+
+    if (val >= 0) {
+       binmode = val;
+    } else {
+       if (my_want_state_is_will(TELOPT_BINARY) &&
+                               my_want_state_is_do(TELOPT_BINARY)) {
+           binmode = 1;
+       } else if (my_want_state_is_wont(TELOPT_BINARY) &&
+                               my_want_state_is_dont(TELOPT_BINARY)) {
+           binmode = 0;
+       }
+       val = binmode ? 0 : 1;
+    }
+
+    if (val == 1) {
+       if (my_want_state_is_will(TELOPT_BINARY) &&
+                                       my_want_state_is_do(TELOPT_BINARY)) {
+           printf("Already operating in binary mode with remote host.\n");
+       } else {
+           printf("Negotiating binary mode with remote host.\n");
+           tel_enter_binary(3);
+       }
+    } else {
+       if (my_want_state_is_wont(TELOPT_BINARY) &&
+                                       my_want_state_is_dont(TELOPT_BINARY)) {
+           printf("Already in network ascii mode with remote host.\n");
+       } else {
+           printf("Negotiating network ascii mode with remote host.\n");
+           tel_leave_binary(3);
+       }
+    }
+    return 1;
+}
+
+    static int
+togrbinary(val)
+    int val;
+{
+    donebinarytoggle = 1;
+
+    if (val == -1)
+       val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
+
+    if (val == 1) {
+       if (my_want_state_is_do(TELOPT_BINARY)) {
+           printf("Already receiving in binary mode.\n");
+       } else {
+           printf("Negotiating binary mode on input.\n");
+           tel_enter_binary(1);
+       }
+    } else {
+       if (my_want_state_is_dont(TELOPT_BINARY)) {
+           printf("Already receiving in network ascii mode.\n");
+       } else {
+           printf("Negotiating network ascii mode on input.\n");
+           tel_leave_binary(1);
+       }
+    }
+    return 1;
+}
+
+    static int
+togxbinary(val)
+    int val;
+{
+    donebinarytoggle = 1;
+
+    if (val == -1)
+       val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
+
+    if (val == 1) {
+       if (my_want_state_is_will(TELOPT_BINARY)) {
+           printf("Already transmitting in binary mode.\n");
+       } else {
+           printf("Negotiating binary mode on output.\n");
+           tel_enter_binary(2);
+       }
+    } else {
+       if (my_want_state_is_wont(TELOPT_BINARY)) {
+           printf("Already transmitting in network ascii mode.\n");
+       } else {
+           printf("Negotiating network ascii mode on output.\n");
+           tel_leave_binary(2);
+       }
+    }
+    return 1;
+}
+
+
+static int togglehelp P((void));
+#if    defined(AUTHENTICATION)
+extern int auth_togdebug P((int));
+#endif
+#ifdef ENCRYPTION
+extern int EncryptAutoEnc P((int));
+extern int EncryptAutoDec P((int));
+extern int EncryptDebug P((int));
+extern int EncryptVerbose P((int));
+#endif /* ENCRYPTION */
+
+struct togglelist {
+    char       *name;          /* name of toggle */
+    char       *help;          /* help message */
+    int                (*handler)();   /* routine to do actual setting */
+    int                *variable;
+    char       *actionexplanation;
+};
+
+static struct togglelist Togglelist[] = {
+    { "autoflush",
+       "flushing of output when sending interrupt characters",
+           0,
+               &autoflush,
+                   "flush output when sending interrupt characters" },
+    { "autosynch",
+       "automatic sending of interrupt characters in urgent mode",
+           0,
+               &autosynch,
+                   "send interrupt characters in urgent mode" },
+#if    defined(AUTHENTICATION)
+    { "autologin",
+       "automatic sending of login and/or authentication info",
+           0,
+               &autologin,
+                   "send login name and/or authentication information" },
+    { "authdebug",
+       "Toggle authentication debugging",
+           auth_togdebug,
+               0,
+                    "print authentication debugging information" },
+#endif
+#ifdef ENCRYPTION
+    { "autoencrypt",
+       "automatic encryption of data stream",
+           EncryptAutoEnc,
+               0,
+                   "automatically encrypt output" },
+    { "autodecrypt",
+       "automatic decryption of data stream",
+           EncryptAutoDec,
+               0,
+                   "automatically decrypt input" },
+    { "verbose_encrypt",
+       "Toggle verbose encryption output",
+           EncryptVerbose,
+               0,
+                   "print verbose encryption output" },
+    { "encdebug",
+       "Toggle encryption debugging",
+           EncryptDebug,
+               0,
+                   "print encryption debugging information" },
+#endif /* ENCRYPTION */
+    { "skiprc",
+       "don't read ~/.telnetrc file",
+           0,
+               &skiprc,
+                   "skip reading of ~/.telnetrc file" },
+    { "binary",
+       "sending and receiving of binary data",
+           togbinary,
+               0,
+                   0 },
+    { "inbinary",
+       "receiving of binary data",
+           togrbinary,
+               0,
+                   0 },
+    { "outbinary",
+       "sending of binary data",
+           togxbinary,
+               0,
+                   0 },
+    { "crlf",
+       "sending carriage returns as telnet <CR><LF>",
+           togcrlf,
+               &crlf,
+                   0 },
+    { "crmod",
+       "mapping of received carriage returns",
+           0,
+               &crmod,
+                   "map carriage return on output" },
+    { "localchars",
+       "local recognition of certain control characters",
+           lclchars,
+               &localchars,
+                   "recognize certain control characters" },
+    { " ", "", 0 },            /* empty line */
+#if    (defined(unix) || defined(__APPLE__)) && defined(TN3270)
+    { "apitrace",
+       "(debugging) toggle tracing of API transactions",
+           0,
+               &apitrace,
+                   "trace API transactions" },
+    { "cursesdata",
+       "(debugging) toggle printing of hexadecimal curses data",
+           0,
+               &cursesdata,
+                   "print hexadecimal representation of curses data" },
+#endif /* (defined(unix) || defined(__APPLE__)) && defined(TN3270) */
+    { "debug",
+       "debugging",
+           togdebug,
+               &debug,
+                   "turn on socket level debugging" },
+    { "netdata",
+       "printing of hexadecimal network data (debugging)",
+           0,
+               &netdata,
+                   "print hexadecimal representation of network traffic" },
+    { "prettydump",
+       "output of \"netdata\" to user readable format (debugging)",
+           0,
+               &prettydump,
+                   "print user readable output for \"netdata\"" },
+    { "options",
+       "viewing of options processing (debugging)",
+           0,
+               &showoptions,
+                   "show option processing" },
+#if    defined(unix) || defined(__APPLE__)
+    { "termdata",
+       "(debugging) toggle printing of hexadecimal terminal data",
+           0,
+               &termdata,
+                   "print hexadecimal representation of terminal traffic" },
+#endif /* defined(unix) || defined(__APPLE__) */
+    { "?",
+       0,
+           togglehelp },
+    { "help",
+       0,
+           togglehelp },
+    { 0 }
+};
+
+    static int
+togglehelp()
+{
+    struct togglelist *c;
+
+    for (c = Togglelist; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s toggle %s\n", c->name, c->help);
+           else
+               printf("\n");
+       }
+    }
+    printf("\n");
+    printf("%-15s %s\n", "?", "display help information");
+    return 0;
+}
+
+    static void
+settogglehelp(set)
+    int set;
+{
+    struct togglelist *c;
+
+    for (c = Togglelist; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
+                                               c->help);
+           else
+               printf("\n");
+       }
+    }
+}
+
+#define        GETTOGGLE(name) (struct togglelist *) \
+               genget(name, (char **) Togglelist, sizeof(struct togglelist))
+
+    static int
+toggle(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    int retval = 1;
+    char *name;
+    struct togglelist *c;
+
+    if (argc < 2) {
+       fprintf(stderr,
+           "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
+       return 0;
+    }
+    argc--;
+    argv++;
+    while (argc--) {
+       name = *argv++;
+       c = GETTOGGLE(name);
+       if (Ambiguous(c)) {
+           fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
+                                       name);
+           return 0;
+       } else if (c == 0) {
+           fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
+                                       name);
+           return 0;
+       } else {
+           if (c->variable) {
+               *c->variable = !*c->variable;           /* invert it */
+               if (c->actionexplanation) {
+                   printf("%s %s.\n", *c->variable? "Will" : "Won't",
+                                                       c->actionexplanation);
+               }
+           }
+           if (c->handler) {
+               retval &= (*c->handler)(-1);
+           }
+       }
+    }
+    return retval;
+}
+\f
+/*
+ * The following perform the "set" command.
+ */
+
+#ifdef USE_TERMIO
+struct termio new_tc = { 0 };
+#endif
+
+struct setlist {
+    char *name;                                /* name */
+    char *help;                                /* help information */
+    void (*handler)();
+    cc_t *charp;                       /* where it is located at */
+};
+
+static struct setlist Setlist[] = {
+#ifdef KLUDGELINEMODE
+    { "echo",  "character to toggle local echoing on/off", 0, &echoc },
+#endif
+    { "escape",        "character to escape back to telnet command mode", 0, &escape },
+    { "rlogin", "rlogin escape character", 0, &rlogin },
+    { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
+    { " ", "" },
+    { " ", "The following need 'localchars' to be toggled true", 0, 0 },
+    { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
+    { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
+    { "quit",  "character to cause an Abort process", 0, termQuitCharp },
+    { "eof",   "character to cause an EOF ", 0, termEofCharp },
+    { " ", "" },
+    { " ", "The following are for local editing in linemode", 0, 0 },
+    { "erase", "character to use to erase a character", 0, termEraseCharp },
+    { "kill",  "character to use to erase a line", 0, termKillCharp },
+    { "lnext", "character to use for literal next", 0, termLiteralNextCharp },
+    { "susp",  "character to cause a Suspend Process", 0, termSuspCharp },
+    { "reprint", "character to use for line reprint", 0, termRprntCharp },
+    { "worderase", "character to use to erase a word", 0, termWerasCharp },
+    { "start", "character to use for XON", 0, termStartCharp },
+    { "stop",  "character to use for XOFF", 0, termStopCharp },
+    { "forw1", "alternate end of line character", 0, termForw1Charp },
+    { "forw2", "alternate end of line character", 0, termForw2Charp },
+    { "ayt",   "alternate AYT character", 0, termAytCharp },
+    { 0 }
+};
+
+#if    defined(CRAY) && !defined(__STDC__)
+/* Work around compiler bug in pcc 4.1.5 */
+    void
+_setlist_init()
+{
+#ifndef        KLUDGELINEMODE
+#define        N 5
+#else
+#define        N 6
+#endif
+       Setlist[N+0].charp = &termFlushChar;
+       Setlist[N+1].charp = &termIntChar;
+       Setlist[N+2].charp = &termQuitChar;
+       Setlist[N+3].charp = &termEofChar;
+       Setlist[N+6].charp = &termEraseChar;
+       Setlist[N+7].charp = &termKillChar;
+       Setlist[N+8].charp = &termLiteralNextChar;
+       Setlist[N+9].charp = &termSuspChar;
+       Setlist[N+10].charp = &termRprntChar;
+       Setlist[N+11].charp = &termWerasChar;
+       Setlist[N+12].charp = &termStartChar;
+       Setlist[N+13].charp = &termStopChar;
+       Setlist[N+14].charp = &termForw1Char;
+       Setlist[N+15].charp = &termForw2Char;
+       Setlist[N+16].charp = &termAytChar;
+#undef N
+}
+#endif /* defined(CRAY) && !defined(__STDC__) */
+
+    static struct setlist *
+getset(name)
+    char *name;
+{
+    return (struct setlist *)
+               genget(name, (char **) Setlist, sizeof(struct setlist));
+}
+
+    void
+set_escape_char(s)
+    char *s;
+{
+       if (rlogin != _POSIX_VDISABLE) {
+               rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
+               printf("Telnet rlogin escape character is '%s'.\n",
+                                       control(rlogin));
+       } else {
+               escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
+               printf("Telnet escape character is '%s'.\n", control(escape));
+       }
+}
+
+    static int
+setcmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    int value;
+    struct setlist *ct;
+    struct togglelist *c;
+
+    if (argc < 2 || argc > 3) {
+       printf("Format is 'set Name Value'\n'set ?' for help.\n");
+       return 0;
+    }
+    if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
+       for (ct = Setlist; ct->name; ct++)
+           printf("%-15s %s\n", ct->name, ct->help);
+       printf("\n");
+       settogglehelp(1);
+       printf("%-15s %s\n", "?", "display help information");
+       return 0;
+    }
+
+    ct = getset(argv[1]);
+    if (ct == 0) {
+       c = GETTOGGLE(argv[1]);
+       if (c == 0) {
+           fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
+                       argv[1]);
+           return 0;
+       } else if (Ambiguous(c)) {
+           fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
+                       argv[1]);
+           return 0;
+       }
+       if (c->variable) {
+           if ((argc == 2) || (strcmp("on", argv[2]) == 0))
+               *c->variable = 1;
+           else if (strcmp("off", argv[2]) == 0)
+               *c->variable = 0;
+           else {
+               printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
+               return 0;
+           }
+           if (c->actionexplanation) {
+               printf("%s %s.\n", *c->variable? "Will" : "Won't",
+                                                       c->actionexplanation);
+           }
+       }
+       if (c->handler)
+           (*c->handler)(1);
+    } else if (argc != 3) {
+       printf("Format is 'set Name Value'\n'set ?' for help.\n");
+       return 0;
+    } else if (Ambiguous(ct)) {
+       fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
+                       argv[1]);
+       return 0;
+    } else if (ct->handler) {
+       (*ct->handler)(argv[2]);
+       printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
+    } else {
+       if (strcmp("off", argv[2])) {
+           value = special(argv[2]);
+       } else {
+           value = _POSIX_VDISABLE;
+       }
+       *(ct->charp) = (cc_t)value;
+       printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
+    }
+    slc_check();
+    return 1;
+}
+
+    static int
+unsetcmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct setlist *ct;
+    struct togglelist *c;
+    register char *name;
+
+    if (argc < 2) {
+       fprintf(stderr,
+           "Need an argument to 'unset' command.  'unset ?' for help.\n");
+       return 0;
+    }
+    if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
+       for (ct = Setlist; ct->name; ct++)
+           printf("%-15s %s\n", ct->name, ct->help);
+       printf("\n");
+       settogglehelp(0);
+       printf("%-15s %s\n", "?", "display help information");
+       return 0;
+    }
+
+    argc--;
+    argv++;
+    while (argc--) {
+       name = *argv++;
+       ct = getset(name);
+       if (ct == 0) {
+           c = GETTOGGLE(name);
+           if (c == 0) {
+               fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
+                       name);
+               return 0;
+           } else if (Ambiguous(c)) {
+               fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
+                       name);
+               return 0;
+           }
+           if (c->variable) {
+               *c->variable = 0;
+               if (c->actionexplanation) {
+                   printf("%s %s.\n", *c->variable? "Will" : "Won't",
+                                                       c->actionexplanation);
+               }
+           }
+           if (c->handler)
+               (*c->handler)(0);
+       } else if (Ambiguous(ct)) {
+           fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
+                       name);
+           return 0;
+       } else if (ct->handler) {
+           (*ct->handler)(0);
+           printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
+       } else {
+           *(ct->charp) = _POSIX_VDISABLE;
+           printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
+       }
+    }
+    return 1;
+}
+\f
+/*
+ * The following are the data structures and routines for the
+ * 'mode' command.
+ */
+#ifdef KLUDGELINEMODE
+extern int kludgelinemode;
+
+    static int
+dokludgemode()
+{
+    kludgelinemode = 1;
+    send_wont(TELOPT_LINEMODE, 1);
+    send_dont(TELOPT_SGA, 1);
+    send_dont(TELOPT_ECHO, 1);
+}
+#endif
+
+    static int
+dolinemode()
+{
+#ifdef KLUDGELINEMODE
+    if (kludgelinemode)
+       send_dont(TELOPT_SGA, 1);
+#endif
+    send_will(TELOPT_LINEMODE, 1);
+    send_dont(TELOPT_ECHO, 1);
+    return 1;
+}
+
+    static int
+docharmode()
+{
+#ifdef KLUDGELINEMODE
+    if (kludgelinemode)
+       send_do(TELOPT_SGA, 1);
+    else
+#endif
+    send_wont(TELOPT_LINEMODE, 1);
+    send_do(TELOPT_ECHO, 1);
+    return 1;
+}
+
+    static int
+dolmmode(bit, on)
+    int bit, on;
+{
+    unsigned char c;
+    extern int linemode;
+
+    if (my_want_state_is_wont(TELOPT_LINEMODE)) {
+       printf("?Need to have LINEMODE option enabled first.\n");
+       printf("'mode ?' for help.\n");
+       return 0;
+    }
+
+    if (on)
+       c = (linemode | bit);
+    else
+       c = (linemode & ~bit);
+    lm_mode(&c, 1, 1);
+    return 1;
+}
+
+    int
+setmode(bit)
+{
+    return dolmmode(bit, 1);
+}
+
+    int
+clearmode(bit)
+{
+    return dolmmode(bit, 0);
+}
+
+struct modelist {
+       char    *name;          /* command name */
+       char    *help;          /* help string */
+       int     (*handler)();   /* routine which executes command */
+       int     needconnect;    /* Do we need to be connected to execute? */
+       int     arg1;
+};
+
+extern int modehelp();
+
+static struct modelist ModeList[] = {
+    { "character", "Disable LINEMODE option",  docharmode, 1 },
+#ifdef KLUDGELINEMODE
+    { "",      "(or disable obsolete line-by-line mode)", 0 },
+#endif
+    { "line",  "Enable LINEMODE option",       dolinemode, 1 },
+#ifdef KLUDGELINEMODE
+    { "",      "(or enable obsolete line-by-line mode)", 0 },
+#endif
+    { "", "", 0 },
+    { "",      "These require the LINEMODE option to be enabled", 0 },
+    { "isig",  "Enable signal trapping",       setmode, 1, MODE_TRAPSIG },
+    { "+isig", 0,                              setmode, 1, MODE_TRAPSIG },
+    { "-isig", "Disable signal trapping",      clearmode, 1, MODE_TRAPSIG },
+    { "edit",  "Enable character editing",     setmode, 1, MODE_EDIT },
+    { "+edit", 0,                              setmode, 1, MODE_EDIT },
+    { "-edit", "Disable character editing",    clearmode, 1, MODE_EDIT },
+    { "softtabs", "Enable tab expansion",      setmode, 1, MODE_SOFT_TAB },
+    { "+softtabs", 0,                          setmode, 1, MODE_SOFT_TAB },
+    { "-softtabs", "Disable character editing",        clearmode, 1, MODE_SOFT_TAB },
+    { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO },
+    { "+litecho", 0,                           setmode, 1, MODE_LIT_ECHO },
+    { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
+    { "help",  0,                              modehelp, 0 },
+#ifdef KLUDGELINEMODE
+    { "kludgeline", 0,                         dokludgemode, 1 },
+#endif
+    { "", "", 0 },
+    { "?",     "Print help information",       modehelp, 0 },
+    { 0 },
+};
+
+
+    int
+modehelp()
+{
+    struct modelist *mt;
+
+    printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
+    for (mt = ModeList; mt->name; mt++) {
+       if (mt->help) {
+           if (*mt->help)
+               printf("%-15s %s\n", mt->name, mt->help);
+           else
+               printf("\n");
+       }
+    }
+    return 0;
+}
+
+#define        GETMODECMD(name) (struct modelist *) \
+               genget(name, (char **) ModeList, sizeof(struct modelist))
+
+    static int
+modecmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct modelist *mt;
+
+    if (argc != 2) {
+       printf("'mode' command requires an argument\n");
+       printf("'mode ?' for help.\n");
+    } else if ((mt = GETMODECMD(argv[1])) == 0) {
+       fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
+    } else if (Ambiguous(mt)) {
+       fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
+    } else if (mt->needconnect && !connected) {
+       printf("?Need to be connected first.\n");
+       printf("'mode ?' for help.\n");
+    } else if (mt->handler) {
+       return (*mt->handler)(mt->arg1);
+    }
+    return 0;
+}
+\f
+/*
+ * The following data structures and routines implement the
+ * "display" command.
+ */
+
+    static int
+display(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct togglelist *tl;
+    struct setlist *sl;
+
+#define        dotog(tl)       if (tl->variable && tl->actionexplanation) { \
+                           if (*tl->variable) { \
+                               printf("will"); \
+                           } else { \
+                               printf("won't"); \
+                           } \
+                           printf(" %s.\n", tl->actionexplanation); \
+                       }
+
+#define        doset(sl)   if (sl->name && *sl->name != ' ') { \
+                       if (sl->handler == 0) \
+                           printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
+                       else \
+                           printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
+                   }
+
+    if (argc == 1) {
+       for (tl = Togglelist; tl->name; tl++) {
+           dotog(tl);
+       }
+       printf("\n");
+       for (sl = Setlist; sl->name; sl++) {
+           doset(sl);
+       }
+    } else {
+       int i;
+
+       for (i = 1; i < argc; i++) {
+           sl = getset(argv[i]);
+           tl = GETTOGGLE(argv[i]);
+           if (Ambiguous(sl) || Ambiguous(tl)) {
+               printf("?Ambiguous argument '%s'.\n", argv[i]);
+               return 0;
+           } else if (!sl && !tl) {
+               printf("?Unknown argument '%s'.\n", argv[i]);
+               return 0;
+           } else {
+               if (tl) {
+                   dotog(tl);
+               }
+               if (sl) {
+                   doset(sl);
+               }
+           }
+       }
+    }
+/*@*/optionstatus();
+#ifdef ENCRYPTION
+    EncryptStatus();
+#endif /* ENCRYPTION */
+    return 1;
+#undef doset
+#undef dotog
+}
+\f
+/*
+ * The following are the data structures, and many of the routines,
+ * relating to command processing.
+ */
+
+/*
+ * Set the escape character.
+ */
+       static int
+setescape(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char *arg;
+       char buf[50];
+
+       printf(
+           "Deprecated usage - please use 'set escape%s%s' in the future.\n",
+                               (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
+       if (argc > 2)
+               arg = argv[1];
+       else {
+               printf("new escape character: ");
+               (void) fgets(buf, sizeof(buf), stdin);
+               arg = buf;
+       }
+       if (arg[0] != '\0')
+               escape = arg[0];
+       if (!In3270) {
+               printf("Escape character is '%s'.\n", control(escape));
+       }
+       (void) fflush(stdout);
+       return 1;
+}
+
+    /*VARARGS*/
+    static int
+togcrmod()
+{
+    crmod = !crmod;
+    printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
+    printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
+    (void) fflush(stdout);
+    return 1;
+}
+
+    /*VARARGS*/
+    int
+suspend()
+{
+#ifdef SIGTSTP
+    setcommandmode();
+    {
+       long oldrows, oldcols, newrows, newcols, err;
+
+       err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+       (void) kill(0, SIGTSTP);
+       /*
+        * If we didn't get the window size before the SUSPEND, but we
+        * can get them now (?), then send the NAWS to make sure that
+        * we are set up for the right window size.
+        */
+       if (TerminalWindowSize(&newrows, &newcols) && connected &&
+           (err || ((oldrows != newrows) || (oldcols != newcols)))) {
+               sendnaws();
+       }
+    }
+    /* reget parameters in case they were changed */
+    TerminalSaveState();
+    setconnmode(0);
+#else
+    printf("Suspend is not supported.  Try the '!' command instead\n");
+#endif
+    return 1;
+}
+
+#if    !defined(TN3270)
+    /*ARGSUSED*/
+    int
+shell(argc, argv)
+    int argc;
+    char *argv[];
+{
+    long oldrows, oldcols, newrows, newcols, err;
+
+    setcommandmode();
+
+    err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+    switch(vfork()) {
+    case -1:
+       perror("Fork failed\n");
+       break;
+
+    case 0:
+       {
+           /*
+            * Fire up the shell in the child.
+            */
+           register char *shellp, *shellname;
+           extern char *strrchr();
+
+           shellp = getenv("SHELL");
+           if (shellp == NULL)
+               shellp = "/bin/sh";
+           if ((shellname = strrchr(shellp, '/')) == 0)
+               shellname = shellp;
+           else
+               shellname++;
+           if (argc > 1)
+               execl(shellp, shellname, "-c", &saveline[1], 0);
+           else
+               execl(shellp, shellname, 0);
+           perror("Execl");
+           _exit(1);
+       }
+    default:
+           (void)wait((int *)0);       /* Wait for the shell to complete */
+
+           if (TerminalWindowSize(&newrows, &newcols) && connected &&
+               (err || ((oldrows != newrows) || (oldcols != newcols)))) {
+                   sendnaws();
+           }
+           break;
+    }
+    return 1;
+}
+#else  /* !defined(TN3270) */
+extern int shell();
+#endif /* !defined(TN3270) */
+
+    /*VARARGS*/
+    static
+bye(argc, argv)
+    int  argc;         /* Number of arguments */
+    char *argv[];      /* arguments */
+{
+    extern int resettermname;
+
+    if (connected) {
+       (void) shutdown(net, 2);
+       printf("Connection closed.\n");
+       (void) NetClose(net);
+       connected = 0;
+       resettermname = 1;
+#if    defined(AUTHENTICATION) || defined(ENCRYPTION)
+       auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+       /* reset options */
+       tninit();
+#if    defined(TN3270)
+       SetIn3270();            /* Get out of 3270 mode */
+#endif /* defined(TN3270) */
+    }
+    if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
+       longjmp(toplevel, 1);
+       /* NOTREACHED */
+    }
+    return 1;                  /* Keep lint, etc., happy */
+}
+
+/*VARARGS*/
+quit()
+{
+       (void) call(bye, "bye", "fromquit", 0);
+       Exit(0);
+       /*NOTREACHED*/
+}
+
+/*VARARGS*/
+       int
+logout()
+{
+       send_do(TELOPT_LOGOUT, 1);
+       (void) netflush();
+       return 1;
+}
+
+\f
+/*
+ * The SLC command.
+ */
+
+struct slclist {
+       char    *name;
+       char    *help;
+       void    (*handler)();
+       int     arg;
+};
+
+static void slc_help();
+
+struct slclist SlcList[] = {
+    { "export",        "Use local special character definitions",
+                                               slc_mode_export,        0 },
+    { "import",        "Use remote special character definitions",
+                                               slc_mode_import,        1 },
+    { "check", "Verify remote special character definitions",
+                                               slc_mode_import,        0 },
+    { "help",  0,                              slc_help,               0 },
+    { "?",     "Print help information",       slc_help,               0 },
+    { 0 },
+};
+
+    static void
+slc_help()
+{
+    struct slclist *c;
+
+    for (c = SlcList; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s %s\n", c->name, c->help);
+           else
+               printf("\n");
+       }
+    }
+}
+
+    static struct slclist *
+getslc(name)
+    char *name;
+{
+    return (struct slclist *)
+               genget(name, (char **) SlcList, sizeof(struct slclist));
+}
+
+    static
+slccmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct slclist *c;
+
+    if (argc != 2) {
+       fprintf(stderr,
+           "Need an argument to 'slc' command.  'slc ?' for help.\n");
+       return 0;
+    }
+    c = getslc(argv[1]);
+    if (c == 0) {
+       fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    if (Ambiguous(c)) {
+       fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    (*c->handler)(c->arg);
+    slcstate();
+    return 1;
+}
+\f
+/*
+ * The ENVIRON command.
+ */
+
+struct envlist {
+       char    *name;
+       char    *help;
+       void    (*handler)();
+       int     narg;
+};
+
+extern struct env_lst *
+       env_define P((unsigned char *, unsigned char *));
+extern void
+       env_undefine P((unsigned char *)),
+       env_export P((unsigned char *)),
+       env_unexport P((unsigned char *)),
+       env_send P((unsigned char *)),
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+       env_varval P((unsigned char *)),
+#endif
+       env_list P((void));
+static void
+       env_help P((void));
+
+struct envlist EnvList[] = {
+    { "define",        "Define an environment variable",
+                                               (void (*)())env_define, 2 },
+    { "undefine", "Undefine an environment variable",
+                                               env_undefine,   1 },
+    { "export",        "Mark an environment variable for automatic export",
+                                               env_export,     1 },
+    { "unexport", "Don't mark an environment variable for automatic export",
+                                               env_unexport,   1 },
+    { "send",  "Send an environment variable", env_send,       1 },
+    { "list",  "List the current environment variables",
+                                               env_list,       0 },
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+    { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
+                                               env_varval,    1 },
+#endif
+    { "help",  0,                              env_help,               0 },
+    { "?",     "Print help information",       env_help,               0 },
+    { 0 },
+};
+
+    static void
+env_help()
+{
+    struct envlist *c;
+
+    for (c = EnvList; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s %s\n", c->name, c->help);
+           else
+               printf("\n");
+       }
+    }
+}
+
+    static struct envlist *
+getenvcmd(name)
+    char *name;
+{
+    return (struct envlist *)
+               genget(name, (char **) EnvList, sizeof(struct envlist));
+}
+
+env_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct envlist *c;
+
+    if (argc < 2) {
+       fprintf(stderr,
+           "Need an argument to 'environ' command.  'environ ?' for help.\n");
+       return 0;
+    }
+    c = getenvcmd(argv[1]);
+    if (c == 0) {
+       fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    if (Ambiguous(c)) {
+       fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    if (c->narg + 2 != argc) {
+       fprintf(stderr,
+           "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
+               c->narg < argc + 2 ? "only " : "",
+               c->narg, c->narg == 1 ? "" : "s", c->name);
+       return 0;
+    }
+    (*c->handler)(argv[2], argv[3]);
+    return 1;
+}
+
+struct env_lst {
+       struct env_lst *next;   /* pointer to next structure */
+       struct env_lst *prev;   /* pointer to previous structure */
+       unsigned char *var;     /* pointer to variable name */
+       unsigned char *value;   /* pointer to variable value */
+       int export;             /* 1 -> export with default list of variables */
+       int welldefined;        /* A well defined variable */
+};
+
+struct env_lst envlisthead;
+
+       struct env_lst *
+env_find(var)
+       unsigned char *var;
+{
+       register struct env_lst *ep;
+
+       for (ep = envlisthead.next; ep; ep = ep->next) {
+               if (strcmp((char *)ep->var, (char *)var) == 0)
+                       return(ep);
+       }
+       return(NULL);
+}
+
+       void
+env_init()
+{
+       extern char **environ;
+       register char **epp, *cp;
+       register struct env_lst *ep;
+       extern char *strchr();
+
+       for (epp = environ; *epp; epp++) {
+               if (cp = strchr(*epp, '=')) {
+                       *cp = '\0';
+                       ep = env_define((unsigned char *)*epp,
+                                       (unsigned char *)cp+1);
+                       ep->export = 0;
+                       *cp = '=';
+               }
+       }
+       /*
+        * Special case for DISPLAY variable.  If it is ":0.0" or
+        * "unix:0.0", we have to get rid of "unix" and insert our
+        * hostname.
+        */
+       if ((ep = env_find("DISPLAY"))
+           && ((*ep->value == ':')
+               || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
+               char hbuf[256+1];
+               char *cp2 = strchr((char *)ep->value, ':');
+
+               gethostname(hbuf, 256);
+               hbuf[256] = '\0';
+               cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
+               sprintf((char *)cp, "%s%s", hbuf, cp2);
+               free(ep->value);
+               ep->value = (unsigned char *)cp;
+       }
+       /*
+        * If USER is not defined, but LOGNAME is, then add
+        * USER with the value from LOGNAME.  By default, we
+        * don't export the USER variable.
+        */
+       if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
+               env_define((unsigned char *)"USER", ep->value);
+               env_unexport((unsigned char *)"USER");
+       }
+       env_export((unsigned char *)"DISPLAY");
+       env_export((unsigned char *)"PRINTER");
+}
+
+       struct env_lst *
+env_define(var, value)
+       unsigned char *var, *value;
+{
+       register struct env_lst *ep;
+
+       if (ep = env_find(var)) {
+               if (ep->var)
+                       free(ep->var);
+               if (ep->value)
+                       free(ep->value);
+       } else {
+               ep = (struct env_lst *)malloc(sizeof(struct env_lst));
+               ep->next = envlisthead.next;
+               envlisthead.next = ep;
+               ep->prev = &envlisthead;
+               if (ep->next)
+                       ep->next->prev = ep;
+       }
+       ep->welldefined = opt_welldefined(var);
+       ep->export = 1;
+       ep->var = (unsigned char *)strdup((char *)var);
+       ep->value = (unsigned char *)strdup((char *)value);
+       return(ep);
+}
+
+       void
+env_undefine(var)
+       unsigned char *var;
+{
+       register struct env_lst *ep;
+
+       if (ep = env_find(var)) {
+               ep->prev->next = ep->next;
+               if (ep->next)
+                       ep->next->prev = ep->prev;
+               if (ep->var)
+                       free(ep->var);
+               if (ep->value)
+                       free(ep->value);
+               free(ep);
+       }
+}
+
+       void
+env_export(var)
+       unsigned char *var;
+{
+       register struct env_lst *ep;
+
+       if (ep = env_find(var))
+               ep->export = 1;
+}
+
+       void
+env_unexport(var)
+       unsigned char *var;
+{
+       register struct env_lst *ep;
+
+       if (ep = env_find(var))
+               ep->export = 0;
+}
+
+       void
+env_send(var)
+       unsigned char *var;
+{
+       register struct env_lst *ep;
+
+       if (my_state_is_wont(TELOPT_NEW_ENVIRON)
+#ifdef OLD_ENVIRON
+           && my_state_is_wont(TELOPT_OLD_ENVIRON)
+#endif
+               ) {
+               fprintf(stderr,
+                   "Cannot send '%s': Telnet ENVIRON option not enabled\n",
+                                                                       var);
+               return;
+       }
+       ep = env_find(var);
+       if (ep == 0) {
+               fprintf(stderr, "Cannot send '%s': variable not defined\n",
+                                                                       var);
+               return;
+       }
+       env_opt_start_info();
+       env_opt_add(ep->var);
+       env_opt_end(0);
+}
+
+       void
+env_list()
+{
+       register struct env_lst *ep;
+
+       for (ep = envlisthead.next; ep; ep = ep->next) {
+               printf("%c %-20s %s\n", ep->export ? '*' : ' ',
+                                       ep->var, ep->value);
+       }
+}
+
+       unsigned char *
+env_default(init, welldefined)
+       int init;
+{
+       static struct env_lst *nep = NULL;
+
+       if (init) {
+               nep = &envlisthead;
+               return;
+       }
+       if (nep) {
+               while (nep = nep->next) {
+                       if (nep->export && (nep->welldefined == welldefined))
+                               return(nep->var);
+               }
+       }
+       return(NULL);
+}
+
+       unsigned char *
+env_getvalue(var)
+       unsigned char *var;
+{
+       register struct env_lst *ep;
+
+       if (ep = env_find(var))
+               return(ep->value);
+       return(NULL);
+}
+
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+       void
+env_varval(what)
+       unsigned char *what;
+{
+       extern int old_env_var, old_env_value, env_auto;
+       int len = strlen((char *)what);
+
+       if (len == 0)
+               goto unknown;
+
+       if (strncasecmp((char *)what, "status", len) == 0) {
+               if (env_auto)
+                       printf("%s%s", "VAR and VALUE are/will be ",
+                                       "determined automatically\n");
+               if (old_env_var == OLD_ENV_VAR)
+                       printf("VAR and VALUE set to correct definitions\n");
+               else
+                       printf("VAR and VALUE definitions are reversed\n");
+       } else if (strncasecmp((char *)what, "auto", len) == 0) {
+               env_auto = 1;
+               old_env_var = OLD_ENV_VALUE;
+               old_env_value = OLD_ENV_VAR;
+       } else if (strncasecmp((char *)what, "right", len) == 0) {
+               env_auto = 0;
+               old_env_var = OLD_ENV_VAR;
+               old_env_value = OLD_ENV_VALUE;
+       } else if (strncasecmp((char *)what, "wrong", len) == 0) {
+               env_auto = 0;
+               old_env_var = OLD_ENV_VALUE;
+               old_env_value = OLD_ENV_VAR;
+       } else {
+unknown:
+               printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
+       }
+}
+#endif
+
+#if    defined(AUTHENTICATION)
+/*
+ * The AUTHENTICATE command.
+ */
+
+struct authlist {
+       char    *name;
+       char    *help;
+       int     (*handler)();
+       int     narg;
+};
+
+extern int
+       auth_enable P((char *)),
+       auth_disable P((char *)),
+       auth_status P((void));
+static int
+       auth_help P((void));
+
+struct authlist AuthList[] = {
+    { "status",        "Display current status of authentication information",
+                                               auth_status,    0 },
+    { "disable", "Disable an authentication type ('auth disable ?' for more)",
+                                               auth_disable,   1 },
+    { "enable", "Enable an authentication type ('auth enable ?' for more)",
+                                               auth_enable,    1 },
+    { "help",  0,                              auth_help,              0 },
+    { "?",     "Print help information",       auth_help,              0 },
+    { 0 },
+};
+
+    static int
+auth_help()
+{
+    struct authlist *c;
+
+    for (c = AuthList; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s %s\n", c->name, c->help);
+           else
+               printf("\n");
+       }
+    }
+    return 0;
+}
+
+auth_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct authlist *c;
+
+    if (argc < 2) {
+       fprintf(stderr,
+           "Need an argument to 'auth' command.  'auth ?' for help.\n");
+       return 0;
+    }
+
+    c = (struct authlist *)
+               genget(argv[1], (char **) AuthList, sizeof(struct authlist));
+    if (c == 0) {
+       fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    if (Ambiguous(c)) {
+       fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    if (c->narg + 2 != argc) {
+       fprintf(stderr,
+           "Need %s%d argument%s to 'auth %s' command.  'auth ?' for help.\n",
+               c->narg < argc + 2 ? "only " : "",
+               c->narg, c->narg == 1 ? "" : "s", c->name);
+       return 0;
+    }
+    return((*c->handler)(argv[2], argv[3]));
+}
+#endif
+
+#ifdef ENCRYPTION
+/*
+ * The ENCRYPT command.
+ */
+
+struct encryptlist {
+       char    *name;
+       char    *help;
+       int     (*handler)();
+       int     needconnect;
+       int     minarg;
+       int     maxarg;
+};
+
+extern int
+       EncryptEnable P((char *, char *)),
+       EncryptDisable P((char *, char *)),
+       EncryptType P((char *, char *)),
+       EncryptStart P((char *)),
+       EncryptStartInput P((void)),
+       EncryptStartOutput P((void)),
+       EncryptStop P((char *)),
+       EncryptStopInput P((void)),
+       EncryptStopOutput P((void)),
+       EncryptStatus P((void));
+static int
+       EncryptHelp P((void));
+
+struct encryptlist EncryptList[] = {
+    { "enable", "Enable encryption. ('encrypt enable ?' for more)",
+                                               EncryptEnable, 1, 1, 2 },
+    { "disable", "Disable encryption. ('encrypt enable ?' for more)",
+                                               EncryptDisable, 0, 1, 2 },
+    { "type", "Set encryption type. ('encrypt type ?' for more)",
+                                               EncryptType, 0, 1, 1 },
+    { "start", "Start encryption. ('encrypt start ?' for more)",
+                                               EncryptStart, 1, 0, 1 },
+    { "stop", "Stop encryption. ('encrypt stop ?' for more)",
+                                               EncryptStop, 1, 0, 1 },
+    { "input", "Start encrypting the input stream",
+                                               EncryptStartInput, 1, 0, 0 },
+    { "-input", "Stop encrypting the input stream",
+                                               EncryptStopInput, 1, 0, 0 },
+    { "output", "Start encrypting the output stream",
+                                               EncryptStartOutput, 1, 0, 0 },
+    { "-output", "Stop encrypting the output stream",
+                                               EncryptStopOutput, 1, 0, 0 },
+
+    { "status",        "Display current status of authentication information",
+                                               EncryptStatus,  0, 0, 0 },
+    { "help",  0,                              EncryptHelp,    0, 0, 0 },
+    { "?",     "Print help information",       EncryptHelp,    0, 0, 0 },
+    { 0 },
+};
+
+    static int
+EncryptHelp()
+{
+    struct encryptlist *c;
+
+    for (c = EncryptList; c->name; c++) {
+       if (c->help) {
+           if (*c->help)
+               printf("%-15s %s\n", c->name, c->help);
+           else
+               printf("\n");
+       }
+    }
+    return 0;
+}
+
+encrypt_cmd(argc, argv)
+    int  argc;
+    char *argv[];
+{
+    struct encryptlist *c;
+
+    if (argc < 2) {
+       fprintf(stderr,
+           "Need an argument to 'encrypt' command.  'encrypt ?' for help.\n");
+       return 0;
+    }
+
+    c = (struct encryptlist *)
+               genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
+    if (c == 0) {
+       fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    if (Ambiguous(c)) {
+       fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n",
+                               argv[1]);
+       return 0;
+    }
+    argc -= 2;
+    if (argc < c->minarg || argc > c->maxarg) {
+       if (c->minarg == c->maxarg) {
+           fprintf(stderr, "Need %s%d argument%s ",
+               c->minarg < argc ? "only " : "", c->minarg,
+               c->minarg == 1 ? "" : "s");
+       } else {
+           fprintf(stderr, "Need %s%d-%d arguments ",
+               c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
+       }
+       fprintf(stderr, "to 'encrypt %s' command.  'encrypt ?' for help.\n",
+               c->name);
+       return 0;
+    }
+    if (c->needconnect && !connected) {
+       if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
+           printf("?Need to be connected first.\n");
+           return 0;
+       }
+    }
+    return ((*c->handler)(argc > 0 ? argv[2] : 0,
+                       argc > 1 ? argv[3] : 0,
+                       argc > 2 ? argv[4] : 0));
+}
+#endif /* ENCRYPTION */
+
+#if    (defined(unix) || defined(__APPLE__)) && defined(TN3270)
+    static void
+filestuff(fd)
+    int fd;
+{
+    int res;
+
+#ifdef F_GETOWN
+    setconnmode(0);
+    res = fcntl(fd, F_GETOWN, 0);
+    setcommandmode();
+
+    if (res == -1) {
+       perror("fcntl");
+       return;
+    }
+    printf("\tOwner is %d.\n", res);
+#endif
+
+    setconnmode(0);
+    res = fcntl(fd, F_GETFL, 0);
+    setcommandmode();
+
+    if (res == -1) {
+       perror("fcntl");
+       return;
+    }
+#ifdef notdef
+    printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
+#endif
+}
+#endif /* (defined(unix) || defined(__APPLE__)) && defined(TN3270) */
+
+/*
+ * Print status about the connection.
+ */
+    /*ARGSUSED*/
+    static
+status(argc, argv)
+    int         argc;
+    char *argv[];
+{
+    if (connected) {
+       printf("Connected to %s.\n", hostname);
+       if ((argc < 2) || strcmp(argv[1], "notmuch")) {
+           int mode = getconnmode();
+
+           if (my_want_state_is_will(TELOPT_LINEMODE)) {
+               printf("Operating with LINEMODE option\n");
+               printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
+               printf("%s catching of signals\n",
+                                       (mode&MODE_TRAPSIG) ? "Local" : "No");
+               slcstate();
+#ifdef KLUDGELINEMODE
+           } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
+               printf("Operating in obsolete linemode\n");
+#endif
+           } else {
+               printf("Operating in single character mode\n");
+               if (localchars)
+                   printf("Catching signals locally\n");
+           }
+           printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
+           if (my_want_state_is_will(TELOPT_LFLOW))
+               printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
+#ifdef ENCRYPTION
+           encrypt_display();
+#endif /* ENCRYPTION */
+       }
+    } else {
+       printf("No connection.\n");
+    }
+#   if !defined(TN3270)
+    printf("Escape character is '%s'.\n", control(escape));
+    (void) fflush(stdout);
+#   else /* !defined(TN3270) */
+    if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
+       printf("Escape character is '%s'.\n", control(escape));
+    }
+#   if defined(unix) || defined(__APPLE__)
+    if ((argc >= 2) && !strcmp(argv[1], "everything")) {
+       printf("SIGIO received %d time%s.\n",
+                               sigiocount, (sigiocount == 1)? "":"s");
+       if (In3270) {
+           printf("Process ID %d, process group %d.\n",
+                                           getpid(), getpgrp(getpid()));
+           printf("Terminal input:\n");
+           filestuff(tin);
+           printf("Terminal output:\n");
+           filestuff(tout);
+           printf("Network socket:\n");
+           filestuff(net);
+       }
+    }
+    if (In3270 && transcom) {
+       printf("Transparent mode command is '%s'.\n", transcom);
+    }
+#   endif /* defined(unix) || defined(__APPLE__) */
+    (void) fflush(stdout);
+    if (In3270) {
+       return 0;
+    }
+#   endif /* defined(TN3270) */
+    return 1;
+}
+
+#ifdef SIGINFO
+/*
+ * Function that gets called when SIGINFO is received.
+ */
+ayt_status()
+{
+    (void) call(status, "status", "notmuch", 0);
+}
+#endif
+
+unsigned long inet_addr();
+
+    int
+tn(argc, argv)
+    int argc;
+    char *argv[];
+{
+    register struct hostent *host = 0;
+    struct sockaddr_in sin;
+    struct servent *sp = 0;
+    unsigned long temp;
+    extern char *inet_ntoa();
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
+    char *srp = 0, *strrchr();
+    unsigned long sourceroute(), srlen;
+#endif
+    char *cmd, *hostp = 0, *portp = 0, *user = 0;
+
+    /* clear the socket address prior to use */
+    memset((char *)&sin, 0, sizeof(sin));
+
+    if (connected) {
+       printf("?Already connected to %s\n", hostname);
+       setuid(getuid());
+       return 0;
+    }
+    if (argc < 2) {
+       (void) strcpy(line, "open ");
+       printf("(to) ");
+       (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
+       makeargv();
+       argc = margc;
+       argv = margv;
+    }
+    cmd = *argv;
+    --argc; ++argv;
+    while (argc) {
+       if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
+           goto usage;
+       if (strcmp(*argv, "-l") == 0) {
+           --argc; ++argv;
+           if (argc == 0)
+               goto usage;
+           user = *argv++;
+           --argc;
+           continue;
+       }
+       if (strcmp(*argv, "-a") == 0) {
+           --argc; ++argv;
+           autologin = 1;
+           continue;
+       }
+       if (hostp == 0) {
+           hostp = *argv++;
+           --argc;
+           continue;
+       }
+       if (portp == 0) {
+           portp = *argv++;
+           --argc;
+           continue;
+       }
+    usage:
+       printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
+       setuid(getuid());
+       return 0;
+    }
+    if (hostp == 0)
+       goto usage;
+
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
+    if (hostp[0] == '@' || hostp[0] == '!') {
+       if ((hostname = strrchr(hostp, ':')) == NULL)
+           hostname = strrchr(hostp, '@');
+       hostname++;
+       srp = 0;
+       temp = sourceroute(hostp, &srp, &srlen);
+       if (temp == 0) {
+           herror(srp);
+           setuid(getuid());
+           return 0;
+       } else if (temp == -1) {
+           printf("Bad source route option: %s\n", hostp);
+           setuid(getuid());
+           return 0;
+       } else {
+           sin.sin_addr.s_addr = temp;
+           sin.sin_family = AF_INET;
+       }
+    } else {
+#endif
+       temp = inet_addr(hostp);
+       if (temp != (unsigned long) -1) {
+           sin.sin_addr.s_addr = temp;
+           sin.sin_family = AF_INET;
+           (void) strcpy(_hostname, hostp);
+           hostname = _hostname;
+       } else {
+           host = gethostbyname(hostp);
+           if (host) {
+               sin.sin_family = host->h_addrtype;
+#if    defined(h_addr)         /* In 4.3, this is a #define */
+               memmove((caddr_t)&sin.sin_addr,
+                               host->h_addr_list[0], host->h_length);
+#else  /* defined(h_addr) */
+               memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
+#endif /* defined(h_addr) */
+               strncpy(_hostname, host->h_name, sizeof(_hostname));
+               _hostname[sizeof(_hostname)-1] = '\0';
+               hostname = _hostname;
+           } else {
+               herror(hostp);
+               setuid(getuid());
+               return 0;
+           }
+       }
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
+    }
+#endif
+    if (portp) {
+       if (*portp == '-') {
+           portp++;
+           telnetport = 1;
+       } else
+           telnetport = 0;
+       sin.sin_port = atoi(portp);
+       if (sin.sin_port == 0) {
+           sp = getservbyname(portp, "tcp");
+           if (sp)
+               sin.sin_port = sp->s_port;
+           else {
+               printf("%s: bad port number\n", portp);
+               setuid(getuid());
+               return 0;
+           }
+       } else {
+#if    !defined(htons)
+           u_short htons P((unsigned short));
+#endif /* !defined(htons) */
+           sin.sin_port = htons(sin.sin_port);
+       }
+    } else {
+       if (sp == 0) {
+           sp = getservbyname("telnet", "tcp");
+           if (sp == 0) {
+               fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
+               setuid(getuid());
+               return 0;
+           }
+           sin.sin_port = sp->s_port;
+       }
+       telnetport = 1;
+    }
+    printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
+    do {
+       net = socket(AF_INET, SOCK_STREAM, 0);
+       setuid(getuid());
+       if (net < 0) {
+           perror("telnet: socket");
+           return 0;
+       }
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
+       if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
+               perror("setsockopt (IP_OPTIONS)");
+#endif
+#if    defined(IPPROTO_IP) && defined(IP_TOS)
+       {
+# if   defined(HAS_GETTOS)
+           struct tosent *tp;
+           if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+               tos = tp->t_tos;
+# endif
+           if (tos < 0)
+               tos = 020;      /* Low Delay bit */
+           if (tos
+               && (setsockopt(net, IPPROTO_IP, IP_TOS,
+                   (char *)&tos, sizeof(int)) < 0)
+               && (errno != ENOPROTOOPT))
+                   perror("telnet: setsockopt (IP_TOS) (ignored)");
+       }
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+       if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
+               perror("setsockopt (SO_DEBUG)");
+       }
+
+       if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
+#if    defined(h_addr)         /* In 4.3, this is a #define */
+           if (host && host->h_addr_list[1]) {
+               int oerrno = errno;
+
+               fprintf(stderr, "telnet: connect to address %s: ",
+                                               inet_ntoa(sin.sin_addr));
+               errno = oerrno;
+               perror((char *)0);
+               host->h_addr_list++;
+               memmove((caddr_t)&sin.sin_addr,
+                       host->h_addr_list[0], host->h_length);
+               (void) NetClose(net);
+               continue;
+           }
+#endif /* defined(h_addr) */
+           perror("telnet: Unable to connect to remote host");
+           return 0;
+       }
+       connected++;
+#if    defined(AUTHENTICATION) || defined(ENCRYPTION)
+       auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+    } while (connected == 0);
+    cmdrc(hostp, hostname);
+    if (autologin && user == NULL) {
+       struct passwd *pw;
+
+       user = getenv("USER");
+       if (user == NULL ||
+           (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
+               if (pw = getpwuid(getuid()))
+                       user = pw->pw_name;
+               else
+                       user = NULL;
+       }
+    }
+    if (user) {
+       env_define((unsigned char *)"USER", (unsigned char *)user);
+       env_export((unsigned char *)"USER");
+    }
+    (void) call(status, "status", "notmuch", 0);
+    if (setjmp(peerdied) == 0)
+       telnet(user);
+    (void) NetClose(net);
+    ExitString("Connection closed by foreign host.\n",1);
+    /*NOTREACHED*/
+}
+
+#define HELPINDENT (sizeof ("connect"))
+
+static char
+       openhelp[] =    "connect to a site",
+       closehelp[] =   "close current connection",
+       logouthelp[] =  "forcibly logout remote user and close the connection",
+       quithelp[] =    "exit telnet",
+       statushelp[] =  "print status information",
+       helphelp[] =    "print help information",
+       sendhelp[] =    "transmit special characters ('send ?' for more)",
+       sethelp[] =     "set operating parameters ('set ?' for more)",
+       unsethelp[] =   "unset operating parameters ('unset ?' for more)",
+       togglestring[] ="toggle operating parameters ('toggle ?' for more)",
+       slchelp[] =     "change state of special charaters ('slc ?' for more)",
+       displayhelp[] = "display operating parameters",
+#if    defined(TN3270) && (defined(unix) || defined(__APPLE__))
+       transcomhelp[] = "specify Unix command for transparent mode pipe",
+#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */
+#if    defined(AUTHENTICATION)
+       authhelp[] =    "turn on (off) authentication ('auth ?' for more)",
+#endif
+#ifdef ENCRYPTION
+       encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)",
+#endif /* ENCRYPTION */
+#if    defined(unix) || defined(__APPLE__)
+       zhelp[] =       "suspend telnet",
+#endif /* defined(unix) || defined(__APPLE__) */
+       shellhelp[] =   "invoke a subshell",
+       envhelp[] =     "change environment variables ('environ ?' for more)",
+       modestring[] = "try to enter line or character mode ('mode ?' for more)";
+
+static int     help();
+
+static Command cmdtab[] = {
+       { "close",      closehelp,      bye,            1 },
+       { "logout",     logouthelp,     logout,         1 },
+       { "display",    displayhelp,    display,        0 },
+       { "mode",       modestring,     modecmd,        0 },
+       { "open",       openhelp,       tn,             0 },
+       { "quit",       quithelp,       quit,           0 },
+       { "send",       sendhelp,       sendcmd,        0 },
+       { "set",        sethelp,        setcmd,         0 },
+       { "unset",      unsethelp,      unsetcmd,       0 },
+       { "status",     statushelp,     status,         0 },
+       { "toggle",     togglestring,   toggle,         0 },
+       { "slc",        slchelp,        slccmd,         0 },
+#if    defined(TN3270) && (defined(unix) || defined(__APPLE__))
+       { "transcom",   transcomhelp,   settranscom,    0 },
+#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */
+#if    defined(AUTHENTICATION)
+       { "auth",       authhelp,       auth_cmd,       0 },
+#endif
+#ifdef ENCRYPTION
+       { "encrypt",    encrypthelp,    encrypt_cmd,    0 },
+#endif /* ENCRYPTION */
+#if    defined(unix) || defined(__APPLE__)
+       { "z",          zhelp,          suspend,        0 },
+#endif /* defined(unix) || defined(__APPLE__) */
+#if    defined(TN3270)
+       { "!",          shellhelp,      shell,          1 },
+#else
+       { "!",          shellhelp,      shell,          0 },
+#endif
+       { "environ",    envhelp,        env_cmd,        0 },
+       { "?",          helphelp,       help,           0 },
+       { 0 }
+};
+
+static char    crmodhelp[] =   "deprecated command -- use 'toggle crmod' instead";
+static char    escapehelp[] =  "deprecated command -- use 'set escape' instead";
+
+static Command cmdtab2[] = {
+       { "help",       0,              help,           0 },
+       { "escape",     escapehelp,     setescape,      0 },
+       { "crmod",      crmodhelp,      togcrmod,       0 },
+       { 0 }
+};
+
+
+/*
+ * Call routine with argc, argv set from args (terminated by 0).
+ */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+
+    /*VARARGS1*/
+    static
+#if __STDC__
+call(intrtn_t routine, ...)
+{
+#else
+call(va_alist)
+    va_dcl
+{
+    intrtn_t routine;
+#endif
+    va_list ap;
+    char *args[100];
+    int argno = 0;
+
+#if __STDC__
+    va_start(ap, routine);
+#else
+    va_start(ap);
+    routine = (va_arg(ap, intrtn_t));
+#endif
+    while ((args[argno++] = va_arg(ap, char *)) != 0) {
+       ;
+    }
+    va_end(ap);
+    return (*routine)(argno-1, args);
+}
+
+
+    static Command *
+getcmd(name)
+    char *name;
+{
+    Command *cm;
+
+    if (cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))
+       return cm;
+    return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
+}
+
+    void
+command(top, tbuf, cnt)
+    int top;
+    char *tbuf;
+    int cnt;
+{
+    register Command *c;
+
+    setcommandmode();
+    if (!top) {
+       putchar('\n');
+#if    defined(unix) || defined(__APPLE__)
+    } else {
+       (void) signal(SIGINT, SIG_DFL);
+       (void) signal(SIGQUIT, SIG_DFL);
+#endif /* defined(unix) || defined(__APPLE__) */
+    }
+    for (;;) {
+       if (rlogin == _POSIX_VDISABLE)
+               printf("%s> ", prompt);
+       if (tbuf) {
+           register char *cp;
+           cp = line;
+           while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
+               cnt--;
+           tbuf = 0;
+           if (cp == line || *--cp != '\n' || cp == line)
+               goto getline;
+           *cp = '\0';
+           if (rlogin == _POSIX_VDISABLE)
+               printf("%s\n", line);
+       } else {
+       getline:
+           if (rlogin != _POSIX_VDISABLE)
+               printf("%s> ", prompt);
+           if (fgets(line, sizeof(line), stdin) == NULL) {
+               if (feof(stdin) || ferror(stdin)) {
+                   (void) quit();
+                   /*NOTREACHED*/
+               }
+               break;
+           }
+       }
+       if (line[0] == 0)
+           break;
+       makeargv();
+       if (margv[0] == 0) {
+           break;
+       }
+       c = getcmd(margv[0]);
+       if (Ambiguous(c)) {
+           printf("?Ambiguous command\n");
+           continue;
+       }
+       if (c == 0) {
+           printf("?Invalid command\n");
+           continue;
+       }
+       if (c->needconnect && !connected) {
+           printf("?Need to be connected first.\n");
+           continue;
+       }
+       if ((*c->handler)(margc, margv)) {
+           break;
+       }
+    }
+    if (!top) {
+       if (!connected) {
+           longjmp(toplevel, 1);
+           /*NOTREACHED*/
+       }
+#if    defined(TN3270)
+       if (shell_active == 0) {
+           setconnmode(0);
+       }
+#else  /* defined(TN3270) */
+       setconnmode(0);
+#endif /* defined(TN3270) */
+    }
+}
+\f
+/*
+ * Help command.
+ */
+       static
+help(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register Command *c;
+
+       if (argc == 1) {
+               printf("Commands may be abbreviated.  Commands are:\n\n");
+               for (c = cmdtab; c->name; c++)
+                       if (c->help) {
+                               printf("%-*s\t%s\n", HELPINDENT, c->name,
+                                                                   c->help);
+                       }
+               return 0;
+       }
+       while (--argc > 0) {
+               register char *arg;
+               arg = *++argv;
+               c = getcmd(arg);
+               if (Ambiguous(c))
+                       printf("?Ambiguous help command %s\n", arg);
+               else if (c == (Command *)0)
+                       printf("?Invalid help command %s\n", arg);
+               else
+                       printf("%s\n", c->help);
+       }
+       return 0;
+}
+
+static char *rcname = 0;
+static char rcbuf[128];
+
+cmdrc(m1, m2)
+       char *m1, *m2;
+{
+    register Command *c;
+    FILE *rcfile;
+    int gotmachine = 0;
+    int l1 = strlen(m1);
+    int l2 = strlen(m2);
+    char m1save[64];
+
+    if (skiprc)
+       return;
+
+    strcpy(m1save, m1);
+    m1 = m1save;
+
+    if (rcname == 0) {
+       rcname = getenv("HOME");
+       if (rcname)
+           strcpy(rcbuf, rcname);
+       else
+           rcbuf[0] = '\0';
+       strcat(rcbuf, "/.telnetrc");
+       rcname = rcbuf;
+    }
+
+    if ((rcfile = fopen(rcname, "r")) == 0) {
+       return;
+    }
+
+    for (;;) {
+       if (fgets(line, sizeof(line), rcfile) == NULL)
+           break;
+       if (line[0] == 0)
+           break;
+       if (line[0] == '#')
+           continue;
+       if (gotmachine) {
+           if (!isspace(line[0]))
+               gotmachine = 0;
+       }
+       if (gotmachine == 0) {
+           if (isspace(line[0]))
+               continue;
+           if (strncasecmp(line, m1, l1) == 0)
+               strncpy(line, &line[l1], sizeof(line) - l1);
+           else if (strncasecmp(line, m2, l2) == 0)
+               strncpy(line, &line[l2], sizeof(line) - l2);
+           else if (strncasecmp(line, "DEFAULT", 7) == 0)
+               strncpy(line, &line[7], sizeof(line) - 7);
+           else
+               continue;
+           if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
+               continue;
+           gotmachine = 1;
+       }
+       makeargv();
+       if (margv[0] == 0)
+           continue;
+       c = getcmd(margv[0]);
+       if (Ambiguous(c)) {
+           printf("?Ambiguous command: %s\n", margv[0]);
+           continue;
+       }
+       if (c == 0) {
+           printf("?Invalid command: %s\n", margv[0]);
+           continue;
+       }
+       /*
+        * This should never happen...
+        */
+       if (c->needconnect && !connected) {
+           printf("?Need to be connected first for %s.\n", margv[0]);
+           continue;
+       }
+       (*c->handler)(margc, margv);
+    }
+    fclose(rcfile);
+}
+
+#if    defined(IP_OPTIONS) && defined(IPPROTO_IP)
+
+/*
+ * Source route is handed in as
+ *     [!]@hop1@hop2...[@|:]dst
+ * If the leading ! is present, it is a
+ * strict source route, otherwise it is
+ * assmed to be a loose source route.
+ *
+ * We fill in the source route option as
+ *     hop1,hop2,hop3...dest
+ * and return a pointer to hop1, which will
+ * be the address to connect() to.
+ *
+ * Arguments:
+ *     arg:    pointer to route list to decipher
+ *
+ *     cpp:    If *cpp is not equal to NULL, this is a
+ *             pointer to a pointer to a character array
+ *             that should be filled in with the option.
+ *
+ *     lenp:   pointer to an integer that contains the
+ *             length of *cpp if *cpp != NULL.
+ *
+ * Return values:
+ *
+ *     Returns the address of the host to connect to.  If the
+ *     return value is -1, there was a syntax error in the
+ *     option, either unknown characters, or too many hosts.
+ *     If the return value is 0, one of the hostnames in the
+ *     path is unknown, and *cpp is set to point to the bad
+ *     hostname.
+ *
+ *     *cpp:   If *cpp was equal to NULL, it will be filled
+ *             in with a pointer to our static area that has
+ *             the option filled in.  This will be 32bit aligned.
+ *
+ *     *lenp:  This will be filled in with how long the option
+ *             pointed to by *cpp is.
+ *
+ */
+       unsigned long
+sourceroute(arg, cpp, lenp)
+       char    *arg;
+       char    **cpp;
+       int     *lenp;
+{
+       static char lsr[44];
+#ifdef sysV88
+       static IOPTN ipopt;
+#endif
+       char *cp, *cp2, *lsrp, *lsrep;
+       register int tmp;
+       struct in_addr sin_addr;
+       register struct hostent *host = 0;
+       register char c;
+
+       /*
+        * Verify the arguments, and make sure we have
+        * at least 7 bytes for the option.
+        */
+       if (cpp == NULL || lenp == NULL)
+               return((unsigned long)-1);
+       if (*cpp != NULL && *lenp < 7)
+               return((unsigned long)-1);
+       /*
+        * Decide whether we have a buffer passed to us,
+        * or if we need to use our own static buffer.
+        */
+       if (*cpp) {
+               lsrp = *cpp;
+               lsrep = lsrp + *lenp;
+       } else {
+               *cpp = lsrp = lsr;
+               lsrep = lsrp + 44;
+       }
+
+       cp = arg;
+
+       /*
+        * Next, decide whether we have a loose source
+        * route or a strict source route, and fill in
+        * the begining of the option.
+        */
+#ifndef        sysV88
+       if (*cp == '!') {
+               cp++;
+               *lsrp++ = IPOPT_SSRR;
+       } else
+               *lsrp++ = IPOPT_LSRR;
+#else
+       if (*cp == '!') {
+               cp++;
+               ipopt.io_type = IPOPT_SSRR;
+       } else
+               ipopt.io_type = IPOPT_LSRR;
+#endif
+
+       if (*cp != '@')
+               return((unsigned long)-1);
+
+#ifndef        sysV88
+       lsrp++;         /* skip over length, we'll fill it in later */
+       *lsrp++ = 4;
+#endif
+
+       cp++;
+
+       sin_addr.s_addr = 0;
+
+       for (c = 0;;) {
+               if (c == ':')
+                       cp2 = 0;
+               else for (cp2 = cp; c = *cp2; cp2++) {
+                       if (c == ',') {
+                               *cp2++ = '\0';
+                               if (*cp2 == '@')
+                                       cp2++;
+                       } else if (c == '@') {
+                               *cp2++ = '\0';
+                       } else if (c == ':') {
+                               *cp2++ = '\0';
+                       } else
+                               continue;
+                       break;
+               }
+               if (!c)
+                       cp2 = 0;
+
+               if ((tmp = inet_addr(cp)) != -1) {
+                       sin_addr.s_addr = tmp;
+               } else if (host = gethostbyname(cp)) {
+#if    defined(h_addr)
+                       memmove((caddr_t)&sin_addr,
+                               host->h_addr_list[0], host->h_length);
+#else
+                       memmove((caddr_t)&sin_addr, host->h_addr, host->h_length);
+#endif
+               } else {
+                       *cpp = cp;
+                       return(0);
+               }
+               memmove(lsrp, (char *)&sin_addr, 4);
+               lsrp += 4;
+               if (cp2)
+                       cp = cp2;
+               else
+                       break;
+               /*
+                * Check to make sure there is space for next address
+                */
+               if (lsrp + 4 > lsrep)
+                       return((unsigned long)-1);
+       }
+#ifndef        sysV88
+       if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
+               *cpp = 0;
+               *lenp = 0;
+               return((unsigned long)-1);
+       }
+       *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
+       *lenp = lsrp - *cpp;
+#else
+       ipopt.io_len = lsrp - *cpp;
+       if (ipopt.io_len <= 5) {                /* Is 3 better ? */
+               *cpp = 0;
+               *lenp = 0;
+               return((unsigned long)-1);
+       }
+       *lenp = sizeof(ipopt);
+       *cpp = (char *) &ipopt;
+#endif
+       return(sin_addr.s_addr);
+}
+#endif
diff --git a/telnet.tproj/defines.h b/telnet.tproj/defines.h
new file mode 100644 (file)
index 0000000..51a9283
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defines.h   8.1 (Berkeley) 6/6/93
+ */
+
+#define        settimer(x)     clocks.x = clocks.system++
+
+#if    !defined(TN3270)
+
+#define        SetIn3270()
+
+#endif /* !defined(TN3270) */
+
+#define        NETADD(c)       { *netoring.supply = c; ring_supplied(&netoring, 1); }
+#define        NET2ADD(c1,c2)  { NETADD(c1); NETADD(c2); }
+#define        NETBYTES()      (ring_full_count(&netoring))
+#define        NETROOM()       (ring_empty_count(&netoring))
+
+#define        TTYADD(c)       if (!(SYNCHing||flushout)) { \
+                               *ttyoring.supply = c; \
+                               ring_supplied(&ttyoring, 1); \
+                       }
+#define        TTYBYTES()      (ring_full_count(&ttyoring))
+#define        TTYROOM()       (ring_empty_count(&ttyoring))
+
+/*     Various modes */
+#define        MODE_LOCAL_CHARS(m)     ((m)&(MODE_EDIT|MODE_TRAPSIG))
+#define        MODE_LOCAL_ECHO(m)      ((m)&MODE_ECHO)
+#define        MODE_COMMAND_LINE(m)    ((m)==-1)
+
+#define        CONTROL(x)      ((x)&0x1f)              /* CTRL(x) is not portable */
diff --git a/telnet.tproj/externs.h b/telnet.tproj/externs.h
new file mode 100644 (file)
index 0000000..006efac
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)externs.h   8.3 (Berkeley) 5/30/95
+ */
+
+#ifndef        BSD
+# define BSD 43
+#endif
+
+/*
+ * ucb stdio.h defines BSD as something wierd
+ */
+#if defined(sun) && defined(__svr4__)
+#define BSD 43
+#endif
+
+#ifndef        USE_TERMIO
+# if BSD > 43 || defined(SYSV_TERMIO)
+#  define USE_TERMIO
+# endif
+#endif
+
+#include <stdio.h>
+#include <setjmp.h>
+#if defined(CRAY) && !defined(NO_BSD_SETJMP)
+#include <bsdsetjmp.h>
+#endif
+#ifndef        FILIO_H
+#include <sys/ioctl.h>
+#else
+#include <sys/filio.h>
+#endif
+#ifdef CRAY
+# include <errno.h>
+#endif /* CRAY */
+#ifdef USE_TERMIO
+# ifndef       VINTR
+#  ifdef SYSV_TERMIO
+#   include <sys/termio.h>
+#  else
+#   include <sys/termios.h>
+#   define termio termios
+#  endif
+# endif
+#endif
+#if defined(NO_CC_T) || !defined(USE_TERMIO)
+# if !defined(USE_TERMIO)
+typedef char cc_t;
+# else
+typedef unsigned char cc_t;
+# endif
+#endif
+
+#ifndef        NO_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#ifndef        _POSIX_VDISABLE
+# ifdef sun
+#  include <sys/param.h>       /* pick up VDISABLE definition, mayby */
+# endif
+# ifdef VDISABLE
+#  define _POSIX_VDISABLE VDISABLE
+# else
+#  define _POSIX_VDISABLE ((cc_t)'\377')
+# endif
+#endif
+
+#define        SUBBUFSIZE      256
+
+#ifndef CRAY
+extern int errno;              /* outside this world */
+#endif /* !CRAY */
+
+#if    !defined(P)
+# ifdef        __STDC__
+#  define      P(x)    x
+# else
+#  define      P(x)    ()
+# endif
+#endif
+
+extern int
+    autologin,         /* Autologin enabled */
+    skiprc,            /* Don't process the ~/.telnetrc file */
+    eight,             /* use eight bit mode (binary in and/or out */
+    flushout,          /* flush output */
+    connected,         /* Are we connected to the other side? */
+    globalmode,                /* Mode tty should be in */
+    In3270,            /* Are we in 3270 mode? */
+    telnetport,                /* Are we connected to the telnet port? */
+    localflow,         /* Flow control handled locally */
+    restartany,                /* If flow control, restart output on any character */
+    localchars,                /* we recognize interrupt/quit */
+    donelclchars,      /* the user has set "localchars" */
+    showoptions,
+    net,               /* Network file descriptor */
+    tin,               /* Terminal input file descriptor */
+    tout,              /* Terminal output file descriptor */
+    crlf,              /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
+    autoflush,         /* flush output when interrupting? */
+    autosynch,         /* send interrupt characters with SYNCH? */
+    SYNCHing,          /* Is the stream in telnet SYNCH mode? */
+    donebinarytoggle,  /* the user has put us in binary */
+    dontlecho,         /* do we suppress local echoing right now? */
+    crmod,
+    netdata,           /* Print out network data flow */
+    prettydump,                /* Print "netdata" output in user readable format */
+#if    defined(unix) || defined(__APPLE__)
+#if    defined(TN3270)
+    cursesdata,                /* Print out curses data flow */
+    apitrace,          /* Trace API transactions */
+#endif /* defined(TN3270) */
+    termdata,          /* Print out terminal data flow */
+#endif /* defined(unix) || defined(__APPLE__) */
+    debug;             /* Debug level */
+
+extern cc_t escape;    /* Escape to command mode */
+extern cc_t rlogin;    /* Rlogin mode escape character */
+#ifdef KLUDGELINEMODE
+extern cc_t echoc;     /* Toggle local echoing */
+#endif
+
+extern char
+    *prompt;           /* Prompt for command. */
+
+extern char
+    doopt[],
+    dont[],
+    will[],
+    wont[],
+    options[],         /* All the little options */
+    *hostname;         /* Who are we connected to? */
+#ifdef ENCRYPTION
+extern void (*encrypt_output) P((unsigned char *, int));
+extern int (*decrypt_input) P((int));
+#endif /* ENCRYPTION */
+
+/*
+ * We keep track of each side of the option negotiation.
+ */
+
+#define        MY_STATE_WILL           0x01
+#define        MY_WANT_STATE_WILL      0x02
+#define        MY_STATE_DO             0x04
+#define        MY_WANT_STATE_DO        0x08
+
+/*
+ * Macros to check the current state of things
+ */
+
+#define        my_state_is_do(opt)             (options[opt]&MY_STATE_DO)
+#define        my_state_is_will(opt)           (options[opt]&MY_STATE_WILL)
+#define my_want_state_is_do(opt)       (options[opt]&MY_WANT_STATE_DO)
+#define my_want_state_is_will(opt)     (options[opt]&MY_WANT_STATE_WILL)
+
+#define        my_state_is_dont(opt)           (!my_state_is_do(opt))
+#define        my_state_is_wont(opt)           (!my_state_is_will(opt))
+#define my_want_state_is_dont(opt)     (!my_want_state_is_do(opt))
+#define my_want_state_is_wont(opt)     (!my_want_state_is_will(opt))
+
+#define        set_my_state_do(opt)            {options[opt] |= MY_STATE_DO;}
+#define        set_my_state_will(opt)          {options[opt] |= MY_STATE_WILL;}
+#define        set_my_want_state_do(opt)       {options[opt] |= MY_WANT_STATE_DO;}
+#define        set_my_want_state_will(opt)     {options[opt] |= MY_WANT_STATE_WILL;}
+
+#define        set_my_state_dont(opt)          {options[opt] &= ~MY_STATE_DO;}
+#define        set_my_state_wont(opt)          {options[opt] &= ~MY_STATE_WILL;}
+#define        set_my_want_state_dont(opt)     {options[opt] &= ~MY_WANT_STATE_DO;}
+#define        set_my_want_state_wont(opt)     {options[opt] &= ~MY_WANT_STATE_WILL;}
+
+/*
+ * Make everything symetrical
+ */
+
+#define        HIS_STATE_WILL                  MY_STATE_DO
+#define        HIS_WANT_STATE_WILL             MY_WANT_STATE_DO
+#define HIS_STATE_DO                   MY_STATE_WILL
+#define HIS_WANT_STATE_DO              MY_WANT_STATE_WILL
+
+#define        his_state_is_do                 my_state_is_will
+#define        his_state_is_will               my_state_is_do
+#define his_want_state_is_do           my_want_state_is_will
+#define his_want_state_is_will         my_want_state_is_do
+
+#define        his_state_is_dont               my_state_is_wont
+#define        his_state_is_wont               my_state_is_dont
+#define his_want_state_is_dont         my_want_state_is_wont
+#define his_want_state_is_wont         my_want_state_is_dont
+
+#define        set_his_state_do                set_my_state_will
+#define        set_his_state_will              set_my_state_do
+#define        set_his_want_state_do           set_my_want_state_will
+#define        set_his_want_state_will         set_my_want_state_do
+
+#define        set_his_state_dont              set_my_state_wont
+#define        set_his_state_wont              set_my_state_dont
+#define        set_his_want_state_dont         set_my_want_state_wont
+#define        set_his_want_state_wont         set_my_want_state_dont
+
+
+extern FILE
+    *NetTrace;         /* Where debugging output goes */
+extern unsigned char
+    NetTraceFile[];    /* Name of file where debugging output goes */
+extern void
+    SetNetTrace P((char *));   /* Function to change where debugging goes */
+
+extern jmp_buf
+    peerdied,
+    toplevel;          /* For error conditions. */
+
+extern void
+    command P((int, char *, int)),
+    Dump P((int, unsigned char *, int)),
+    init_3270 P((void)),
+    printoption P((char *, int, int)),
+    printsub P((int, unsigned char *, int)),
+    sendnaws P((void)),
+    setconnmode P((int)),
+    setcommandmode P((void)),
+    setneturg P((void)),
+    sys_telnet_init P((void)),
+    telnet P((char *)),
+    tel_enter_binary P((int)),
+    TerminalFlushOutput P((void)),
+    TerminalNewMode P((int)),
+    TerminalRestoreState P((void)),
+    TerminalSaveState P((void)),
+    tninit P((void)),
+    upcase P((char *)),
+    willoption P((int)),
+    wontoption P((int));
+
+extern void
+    send_do P((int, int)),
+    send_dont P((int, int)),
+    send_will P((int, int)),
+    send_wont P((int, int));
+
+extern void
+    lm_will P((unsigned char *, int)),
+    lm_wont P((unsigned char *, int)),
+    lm_do P((unsigned char *, int)),
+    lm_dont P((unsigned char *, int)),
+    lm_mode P((unsigned char *, int, int));
+
+extern void
+    slc_init P((void)),
+    slcstate P((void)),
+    slc_mode_export P((void)),
+    slc_mode_import P((int)),
+    slc_import P((int)),
+    slc_export P((void)),
+    slc P((unsigned char *, int)),
+    slc_check P((void)),
+    slc_start_reply P((void)),
+    slc_add_reply P((int, int, int)),
+    slc_end_reply P((void));
+extern int
+    slc_update P((void));
+
+extern void
+    env_opt P((unsigned char *, int)),
+    env_opt_start P((void)),
+    env_opt_start_info P((void)),
+    env_opt_add P((unsigned char *)),
+    env_opt_end P((int));
+
+extern unsigned char
+    *env_default P((int, int)),
+    *env_getvalue P((unsigned char *));
+
+extern int
+    get_status P((void)),
+    dosynch P((void));
+
+extern cc_t
+    *tcval P((int));
+
+#ifndef        USE_TERMIO
+
+extern struct  tchars ntc;
+extern struct  ltchars nltc;
+extern struct  sgttyb nttyb;
+
+# define termEofChar           ntc.t_eofc
+# define termEraseChar         nttyb.sg_erase
+# define termFlushChar         nltc.t_flushc
+# define termIntChar           ntc.t_intrc
+# define termKillChar          nttyb.sg_kill
+# define termLiteralNextChar   nltc.t_lnextc
+# define termQuitChar          ntc.t_quitc
+# define termSuspChar          nltc.t_suspc
+# define termRprntChar         nltc.t_rprntc
+# define termWerasChar         nltc.t_werasc
+# define termStartChar         ntc.t_startc
+# define termStopChar          ntc.t_stopc
+# define termForw1Char         ntc.t_brkc
+extern cc_t termForw2Char;
+extern cc_t termAytChar;
+
+# define termEofCharp          (cc_t *)&ntc.t_eofc
+# define termEraseCharp                (cc_t *)&nttyb.sg_erase
+# define termFlushCharp                (cc_t *)&nltc.t_flushc
+# define termIntCharp          (cc_t *)&ntc.t_intrc
+# define termKillCharp         (cc_t *)&nttyb.sg_kill
+# define termLiteralNextCharp  (cc_t *)&nltc.t_lnextc
+# define termQuitCharp         (cc_t *)&ntc.t_quitc
+# define termSuspCharp         (cc_t *)&nltc.t_suspc
+# define termRprntCharp                (cc_t *)&nltc.t_rprntc
+# define termWerasCharp                (cc_t *)&nltc.t_werasc
+# define termStartCharp                (cc_t *)&ntc.t_startc
+# define termStopCharp         (cc_t *)&ntc.t_stopc
+# define termForw1Charp                (cc_t *)&ntc.t_brkc
+# define termForw2Charp                (cc_t *)&termForw2Char
+# define termAytCharp          (cc_t *)&termAytChar
+
+# else
+
+extern struct  termio new_tc;
+
+# define termEofChar           new_tc.c_cc[VEOF]
+# define termEraseChar         new_tc.c_cc[VERASE]
+# define termIntChar           new_tc.c_cc[VINTR]
+# define termKillChar          new_tc.c_cc[VKILL]
+# define termQuitChar          new_tc.c_cc[VQUIT]
+
+# ifndef       VSUSP
+extern cc_t termSuspChar;
+# else
+#  define termSuspChar         new_tc.c_cc[VSUSP]
+# endif
+# if   defined(VFLUSHO) && !defined(VDISCARD)
+#  define VDISCARD VFLUSHO
+# endif
+# ifndef       VDISCARD
+extern cc_t termFlushChar;
+# else
+#  define termFlushChar                new_tc.c_cc[VDISCARD]
+# endif
+# ifndef VWERASE
+extern cc_t termWerasChar;
+# else
+#  define termWerasChar                new_tc.c_cc[VWERASE]
+# endif
+# ifndef       VREPRINT
+extern cc_t termRprntChar;
+# else
+#  define termRprntChar                new_tc.c_cc[VREPRINT]
+# endif
+# ifndef       VLNEXT
+extern cc_t termLiteralNextChar;
+# else
+#  define termLiteralNextChar  new_tc.c_cc[VLNEXT]
+# endif
+# ifndef       VSTART
+extern cc_t termStartChar;
+# else
+#  define termStartChar                new_tc.c_cc[VSTART]
+# endif
+# ifndef       VSTOP
+extern cc_t termStopChar;
+# else
+#  define termStopChar         new_tc.c_cc[VSTOP]
+# endif
+# ifndef       VEOL
+extern cc_t termForw1Char;
+# else
+#  define termForw1Char                new_tc.c_cc[VEOL]
+# endif
+# ifndef       VEOL2
+extern cc_t termForw2Char;
+# else
+#  define termForw2Char                new_tc.c_cc[VEOL]
+# endif
+# ifndef       VSTATUS
+extern cc_t termAytChar;
+#else
+#  define termAytChar          new_tc.c_cc[VSTATUS]
+#endif
+
+# if !defined(CRAY) || defined(__STDC__)
+#  define termEofCharp         &termEofChar
+#  define termEraseCharp       &termEraseChar
+#  define termIntCharp         &termIntChar
+#  define termKillCharp                &termKillChar
+#  define termQuitCharp                &termQuitChar
+#  define termSuspCharp                &termSuspChar
+#  define termFlushCharp       &termFlushChar
+#  define termWerasCharp       &termWerasChar
+#  define termRprntCharp       &termRprntChar
+#  define termLiteralNextCharp &termLiteralNextChar
+#  define termStartCharp       &termStartChar
+#  define termStopCharp                &termStopChar
+#  define termForw1Charp       &termForw1Char
+#  define termForw2Charp       &termForw2Char
+#  define termAytCharp         &termAytChar
+# else
+       /* Work around a compiler bug */
+#  define termEofCharp         0
+#  define termEraseCharp       0
+#  define termIntCharp         0
+#  define termKillCharp                0
+#  define termQuitCharp                0
+#  define termSuspCharp                0
+#  define termFlushCharp       0
+#  define termWerasCharp       0
+#  define termRprntCharp       0
+#  define termLiteralNextCharp 0
+#  define termStartCharp       0
+#  define termStopCharp                0
+#  define termForw1Charp       0
+#  define termForw2Charp       0
+#  define termAytCharp         0
+# endif
+#endif
+
+
+/* Ring buffer structures which are shared */
+
+extern Ring
+    netoring,
+    netiring,
+    ttyoring,
+    ttyiring;
+
+/* Tn3270 section */
+#if    defined(TN3270)
+
+extern int
+    HaveInput,         /* Whether an asynchronous I/O indication came in */
+    noasynchtty,       /* Don't do signals on I/O (SIGURG, SIGIO) */
+    noasynchnet,       /* Don't do signals on I/O (SIGURG, SIGIO) */
+    sigiocount,                /* Count of SIGIO receptions */
+    shell_active;      /* Subshell is active */
+
+extern char
+    *Ibackp,           /* Oldest byte of 3270 data */
+    Ibuf[],            /* 3270 buffer */
+    *Ifrontp,          /* Where next 3270 byte goes */
+    tline[],
+    *transcom;         /* Transparent command */
+
+extern int
+    settranscom P((int, char**));
+
+extern void
+    inputAvailable P((int));
+#endif /* defined(TN3270) */
diff --git a/telnet.tproj/fdset.h b/telnet.tproj/fdset.h
new file mode 100644 (file)
index 0000000..d0f290a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)fdset.h     8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * The following is defined just in case someone should want to run
+ * this telnet on a 4.2 system.
+ *
+ */
+
+#ifndef        FD_SETSIZE
+
+#define        FD_SET(n, p)    ((p)->fds_bits[0] |= (1<<(n)))
+#define        FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1<<(n)))
+#define        FD_ISSET(n, p)  ((p)->fds_bits[0] & (1<<(n)))
+#define FD_ZERO(p)     ((p)->fds_bits[0] = 0)
+
+#endif
diff --git a/telnet.tproj/general.h b/telnet.tproj/general.h
new file mode 100644 (file)
index 0000000..303ae14
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)general.h   8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Some general definitions.
+ */
+
+
+#define        numberof(x)     (sizeof x/sizeof x[0])
+#define        highestof(x)    (numberof(x)-1)
+
+#define        ClearElement(x)         memset((char *)&x, 0, sizeof x)
+#define        ClearArray(x)           memset((char *)x, 0, sizeof x)
diff --git a/telnet.tproj/krb4-proto.h b/telnet.tproj/krb4-proto.h
new file mode 100644 (file)
index 0000000..9f3f0b0
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifdef __STDC__
+# define       P(s) s
+#else
+# define P(s) ()
+#endif
+
+/* add_ticket.c */
+int add_ticket P((KTEXT , int , char *, int , char *, char *, char *, int , KTEXT ));
+
+/* cr_err_reply.c */
+void cr_err_reply P((KTEXT , char *, char *, char *, u_long , u_long , char *));
+
+/* create_auth_reply.c */
+KTEXT create_auth_reply P((char *, char *, char *, long , int , unsigned long , int , KTEXT ));
+
+/* create_ciph.c */
+int create_ciph P((KTEXT , C_Block , char *, char *, char *, unsigned long , int , KTEXT , unsigned long , C_Block ));
+
+/* create_death_packet.c */
+KTEXT krb_create_death_packet P((char *));
+
+/* create_ticket.c */
+int krb_create_ticket P((KTEXT , unsigned int , char *, char *, char *, long , char *, int , long , char *, char *, C_Block ));
+
+/* debug_decl.c */
+
+/* decomp_ticket.c */
+int decomp_ticket P((KTEXT , unsigned char *, char *, char *, char *, unsigned long *, C_Block , int *, unsigned long *, char *, char *, C_Block , Key_schedule ));
+
+/* dest_tkt.c */
+int dest_tkt P((void ));
+
+/* extract_ticket.c */
+int extract_ticket P((KTEXT , int , char *, int *, int *, char *, KTEXT ));
+
+/* fgetst.c */
+int fgetst P((FILE *, char *, int ));
+
+/* get_ad_tkt.c */
+int get_ad_tkt P((char *, char *, char *, int ));
+
+/* get_admhst.c */
+int krb_get_admhst P((char *, char *, int ));
+
+/* get_cred.c */
+int krb_get_cred P((char *, char *, char *, CREDENTIALS *));
+
+/* get_in_tkt.c */
+int krb_get_pw_in_tkt P((char *, char *, char *, char *, char *, int , char *));
+int placebo_read_password P((des_cblock *, char *, int ));
+int placebo_read_pw_string P((char *, int , char *, int ));
+
+/* get_krbhst.c */
+int krb_get_krbhst P((char *, char *, int ));
+
+/* get_krbrlm.c */
+int krb_get_lrealm P((char *, int ));
+
+/* get_phost.c */
+char *krb_get_phost P((char *));
+
+/* get_pw_tkt.c */
+int get_pw_tkt P((char *, char *, char *, char *));
+
+/* get_request.c */
+int get_request P((KTEXT , int , char **, char **));
+
+/* get_svc_in_tkt.c */
+int krb_get_svc_in_tkt P((char *, char *, char *, char *, char *, int , char *));
+
+/* get_tf_fullname.c */
+int krb_get_tf_fullname P((char *, char *, char *, char *));
+
+/* get_tf_realm.c */
+int krb_get_tf_realm P((char *, char *));
+
+/* getopt.c */
+int getopt P((int , char **, char *));
+
+/* getrealm.c */
+char *krb_realmofhost P((char *));
+
+/* getst.c */
+int getst P((int , char *, int ));
+
+/* in_tkt.c */
+int in_tkt P((char *, char *));
+
+/* k_gethostname.c */
+int k_gethostname P((char *, int ));
+
+/* klog.c */
+char *klog P((int , char *, int , int , int , int , int , int , int , int , int , int ));
+int kset_logfile P((char *));
+
+/* kname_parse.c */
+int kname_parse P((char *, char *, char *, char *));
+int k_isname P((char *));
+int k_isinst P((char *));
+int k_isrealm P((char *));
+
+/* kntoln.c */
+int krb_kntoln P((AUTH_DAT *, char *));
+
+/* krb_err_txt.c */
+
+/* krb_get_in_tkt.c */
+int krb_get_in_tkt P((char *, char *, char *, char *, char *, int , int (*key_proc )(), int (*decrypt_proc )(), char *));
+
+/* kuserok.c */
+int kuserok P((AUTH_DAT *, char *));
+
+/* log.c */
+void log P((char *, int , int , int , int , int , int , int , int , int , int ));
+int set_logfile P((char *));
+int new_log P((long , char *));
+
+/* mk_err.c */
+long krb_mk_err P((u_char *, long , char *));
+
+/* mk_priv.c */
+long krb_mk_priv P((u_char *, u_char *, u_long , Key_schedule , C_Block , struct sockaddr_in *, struct sockaddr_in *));
+
+/* mk_req.c */
+int krb_mk_req P((KTEXT , char *, char *, char *, long ));
+int krb_set_lifetime P((int ));
+
+/* mk_safe.c */
+long krb_mk_safe P((u_char *, u_char *, u_long , C_Block *, struct sockaddr_in *, struct sockaddr_in *));
+
+/* month_sname.c */
+char *month_sname P((int ));
+
+/* netread.c */
+int krb_net_read P((int , char *, int ));
+
+/* netwrite.c */
+int krb_net_write P((int , char *, int ));
+
+/* one.c */
+
+/* pkt_cipher.c */
+KTEXT pkt_cipher P((KTEXT ));
+
+/* pkt_clen.c */
+int pkt_clen P((KTEXT ));
+
+/* rd_err.c */
+int krb_rd_err P((u_char *, u_long , long *, MSG_DAT *));
+
+/* rd_priv.c */
+long krb_rd_priv P((u_char *, u_long , Key_schedule , C_Block , struct sockaddr_in *, struct sockaddr_in *, MSG_DAT *));
+
+/* rd_req.c */
+int krb_set_key P((char *, int ));
+int krb_rd_req P((KTEXT , char *, char *, long , AUTH_DAT *, char *));
+
+/* rd_safe.c */
+long krb_rd_safe P((u_char *, u_long , C_Block *, struct sockaddr_in *, struct sockaddr_in *, MSG_DAT *));
+
+/* read_service_key.c */
+int read_service_key P((char *, char *, char *, int , char *, char *));
+
+/* recvauth.c */
+int krb_recvauth P((long , int , KTEXT , char *, char *, struct sockaddr_in *, struct sockaddr_in *, AUTH_DAT *, char *, Key_schedule , char *));
+
+/* save_credentials.c */
+int save_credentials P((char *, char *, char *, C_Block , int , int , KTEXT , long ));
+
+/* send_to_kdc.c */
+int send_to_kdc P((KTEXT , KTEXT , char *));
+
+/* sendauth.c */
+int krb_sendauth P((long , int , KTEXT , char *, char *, char *, u_long , MSG_DAT *, CREDENTIALS *, Key_schedule , struct sockaddr_in *, struct sockaddr_in *, char *));
+int krb_sendsvc P((int , char *));
+
+/* setenv.c */
+int setenv P((char *, char *, int ));
+void unsetenv P((char *));
+char *getenv P((char *));
+char *_findenv P((char *, int *));
+
+/* stime.c */
+char *stime P((long *));
+
+/* tf_shm.c */
+int krb_shm_create P((char *));
+int krb_is_diskless P((void ));
+int krb_shm_dest P((char *));
+
+/* tf_util.c */
+int tf_init P((char *, int ));
+int tf_get_pname P((char *));
+int tf_get_pinst P((char *));
+int tf_get_cred P((CREDENTIALS *));
+int tf_close P((void ));
+int tf_save_cred P((char *, char *, char *, C_Block , int , int , KTEXT , long ));
+
+/* tkt_string.c */
+char *tkt_string P((void ));
+void krb_set_tkt_string P((char *));
+
+/* util.c */
+int ad_print P((AUTH_DAT *));
+int placebo_cblock_print P((des_cblock ));
+
+#undef P
diff --git a/telnet.tproj/main.c b/telnet.tproj/main.c
new file mode 100644 (file)
index 0000000..94cbfc8
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1990, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c     8.3 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include "ring.h"
+#include "externs.h"
+#include "defines.h"
+
+/* These values need to be the same as defined in libtelnet/kerberos5.c */
+/* Either define them in both places, or put in some common header file. */
+#define OPTS_FORWARD_CREDS     0x00000002
+#define OPTS_FORWARDABLE_CREDS 0x00000001
+
+#if 0
+#define FORWARD
+#endif
+
+/*
+ * Initialize variables.
+ */
+    void
+tninit()
+{
+    init_terminal();
+
+    init_network();
+
+    init_telnet();
+
+    init_sys();
+
+#if defined(TN3270)
+    init_3270();
+#endif
+}
+
+       void
+usage()
+{
+       fprintf(stderr, "Usage: %s %s%s%s%s\n",
+           prompt,
+#ifdef AUTHENTICATION
+           "[-8] [-E] [-K] [-L] [-S tos] [-X atype] [-a] [-c] [-d] [-e char]",
+           "\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] ",
+#else
+           "[-8] [-E] [-L] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
+           "\n\t[-n tracefile]",
+#endif
+#if defined(TN3270) && (defined(unix) || defined(__APPLE__))
+# ifdef AUTHENTICATION
+           "[-noasynch] [-noasynctty]\n\t[-noasyncnet] [-r] [-t transcom] ",
+# else
+           "[-noasynch] [-noasynctty] [-noasyncnet] [-r]\n\t[-t transcom]",
+# endif
+#else
+           "[-r] ",
+#endif
+#ifdef ENCRYPTION
+           "[-x] [host-name [port]]"
+#else  /* ENCRYPTION */
+           "[host-name [port]]"
+#endif /* ENCRYPTION */
+       );
+       exit(1);
+}
+
+/*
+ * main.  Parse arguments, invoke the protocol or command parser.
+ */
+
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern char *optarg;
+       extern int optind;
+       int ch;
+       char *user, *strrchr();
+#ifdef FORWARD
+       extern int forward_flags;
+#endif /* FORWARD */
+
+       tninit();               /* Clear out things */
+#if    defined(CRAY) && !defined(__STDC__)
+       _setlist_init();        /* Work around compiler bug */
+#endif
+
+       TerminalSaveState();
+
+       if (prompt = strrchr(argv[0], '/'))
+               ++prompt;
+       else
+               prompt = argv[0];
+
+       user = NULL;
+
+       rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
+       autologin = -1;
+
+       while ((ch = getopt(argc, argv, "8EKLS:X:acde:fFk:l:n:rt:x")) != EOF) {
+               switch(ch) {
+               case '8':
+                       eight = 3;      /* binary output and input */
+                       break;
+               case 'E':
+                       rlogin = escape = _POSIX_VDISABLE;
+                       break;
+               case 'K':
+#ifdef AUTHENTICATION
+                       autologin = 0;
+#endif
+                       break;
+               case 'L':
+                       eight |= 2;     /* binary output only */
+                       break;
+               case 'S':
+                   {
+#ifdef HAS_GETTOS
+                       extern int tos;
+
+                       if ((tos = parsetos(optarg, "tcp")) < 0)
+                               fprintf(stderr, "%s%s%s%s\n",
+                                       prompt, ": Bad TOS argument '",
+                                       optarg,
+                                       "; will try to use default TOS");
+#else
+                       fprintf(stderr,
+                          "%s: Warning: -S ignored, no parsetos() support.\n",
+                                                               prompt);
+#endif
+                   }
+                       break;
+               case 'X':
+#ifdef AUTHENTICATION
+                       auth_disable_name(optarg);
+#endif
+                       break;
+               case 'a':
+                       autologin = 1;
+                       break;
+               case 'c':
+                       skiprc = 1;
+                       break;
+               case 'd':
+                       debug = 1;
+                       break;
+               case 'e':
+                       set_escape_char(optarg);
+                       break;
+               case 'f':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+                       if (forward_flags & OPTS_FORWARD_CREDS) {
+                           fprintf(stderr,
+                                   "%s: Only one of -f and -F allowed.\n",
+                                   prompt);
+                           usage();
+                       }
+                       forward_flags |= OPTS_FORWARD_CREDS;
+#else
+                       fprintf(stderr,
+                        "%s: Warning: -f ignored, no Kerberos V5 support.\n",
+                               prompt);
+#endif
+                       break;
+               case 'F':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+                       if (forward_flags & OPTS_FORWARD_CREDS) {
+                           fprintf(stderr,
+                                   "%s: Only one of -f and -F allowed.\n",
+                                   prompt);
+                           usage();
+                       }
+                       forward_flags |= OPTS_FORWARD_CREDS;
+                       forward_flags |= OPTS_FORWARDABLE_CREDS;
+#else
+                       fprintf(stderr,
+                        "%s: Warning: -F ignored, no Kerberos V5 support.\n",
+                               prompt);
+#endif
+                       break;
+               case 'k':
+#if defined(AUTHENTICATION) && defined(KRB4)
+                   {
+                       extern char *dest_realm, dst_realm_buf[], dst_realm_sz;
+                       dest_realm = dst_realm_buf;
+                       (void)strncpy(dest_realm, optarg, dst_realm_sz);
+                   }
+#else
+                       fprintf(stderr,
+                          "%s: Warning: -k ignored, no Kerberos V4 support.\n",
+                                                               prompt);
+#endif
+                       break;
+               case 'l':
+                       autologin = 1;
+                       user = optarg;
+                       break;
+               case 'n':
+#if defined(TN3270) && (defined(unix) || defined(__APPLE__))
+                       /* distinguish between "-n oasynch" and "-noasynch" */
+                       if (argv[optind - 1][0] == '-' && argv[optind - 1][1]
+                           == 'n' && argv[optind - 1][2] == 'o') {
+                               if (!strcmp(optarg, "oasynch")) {
+                                       noasynchtty = 1;
+                                       noasynchnet = 1;
+                               } else if (!strcmp(optarg, "oasynchtty"))
+                                       noasynchtty = 1;
+                               else if (!strcmp(optarg, "oasynchnet"))
+                                       noasynchnet = 1;
+                       } else
+#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */
+                               SetNetTrace(optarg);
+                       break;
+               case 'r':
+                       rlogin = '~';
+                       break;
+               case 't':
+#if defined(TN3270) && (defined(unix) || defined(__APPLE__))
+                       transcom = tline;
+                       (void)strcpy(transcom, optarg);
+#else
+                       fprintf(stderr,
+                          "%s: Warning: -t ignored, no TN3270 support.\n",
+                                                               prompt);
+#endif
+                       break;
+               case 'x':
+#ifdef ENCRYPTION
+                       encrypt_auto(1);
+                       decrypt_auto(1);
+#else  /* ENCRYPTION */
+                       fprintf(stderr,
+                           "%s: Warning: -x ignored, no ENCRYPT support.\n",
+                                                               prompt);
+#endif /* ENCRYPTION */
+                       break;
+               case '?':
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+       if (autologin == -1)
+               autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
+
+       argc -= optind;
+       argv += optind;
+
+       if (argc) {
+               char *args[7], **argp = args;
+
+               if (argc > 2)
+                       usage();
+               *argp++ = prompt;
+               if (user) {
+                       *argp++ = "-l";
+                       *argp++ = user;
+               }
+               *argp++ = argv[0];              /* host */
+               if (argc > 1)
+                       *argp++ = argv[1];      /* port */
+               *argp = 0;
+
+               if (setjmp(toplevel) != 0)
+                       Exit(0);
+               if (tn(argp - args, args) == 1)
+                       return (0);
+               else
+                       return (1);
+       }
+       (void)setjmp(toplevel);
+       for (;;) {
+#ifdef TN3270
+               if (shell_active)
+                       shell_continue();
+               else
+#endif
+                       command(1, 0, 0);
+       }
+}
diff --git a/telnet.tproj/network.c b/telnet.tproj/network.c
new file mode 100644 (file)
index 0000000..27cc7bd
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)network.c  8.2 (Berkeley) 12/15/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <errno.h>
+
+#include <arpa/telnet.h>
+
+#include "ring.h"
+
+#include "defines.h"
+#include "externs.h"
+#include "fdset.h"
+
+Ring           netoring, netiring;
+unsigned char  netobuf[2*BUFSIZ], netibuf[BUFSIZ];
+
+/*
+ * Initialize internal network data structures.
+ */
+
+    void
+init_network()
+{
+    if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
+       exit(1);
+    }
+    if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
+       exit(1);
+    }
+    NetTrace = stdout;
+}
+
+
+/*
+ * Check to see if any out-of-band data exists on a socket (for
+ * Telnet "synch" processing).
+ */
+
+    int
+stilloob()
+{
+    static struct timeval timeout = { 0 };
+    fd_set     excepts;
+    int value;
+
+    do {
+       FD_ZERO(&excepts);
+       FD_SET(net, &excepts);
+       value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
+    } while ((value == -1) && (errno == EINTR));
+
+    if (value < 0) {
+       perror("select");
+       (void) quit();
+       /* NOTREACHED */
+    }
+    if (FD_ISSET(net, &excepts)) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+
+/*
+ *  setneturg()
+ *
+ *     Sets "neturg" to the current location.
+ */
+
+    void
+setneturg()
+{
+    ring_mark(&netoring);
+}
+
+
+/*
+ *  netflush
+ *             Send as much data as possible to the network,
+ *     handling requests for urgent data.
+ *
+ *             The return value indicates whether we did any
+ *     useful work.
+ */
+
+
+    int
+netflush()
+{
+    register int n, n1;
+
+#ifdef ENCRYPTION
+    if (encrypt_output)
+       ring_encrypt(&netoring, encrypt_output);
+#endif /* ENCRYPTION */
+    if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
+       if (!ring_at_mark(&netoring)) {
+           n = send(net, (char *)netoring.consume, n, 0); /* normal write */
+       } else {
+           /*
+            * In 4.2 (and 4.3) systems, there is some question about
+            * what byte in a sendOOB operation is the "OOB" data.
+            * To make ourselves compatible, we only send ONE byte
+            * out of band, the one WE THINK should be OOB (though
+            * we really have more the TCP philosophy of urgent data
+            * rather than the Unix philosophy of OOB data).
+            */
+           n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
+       }
+    }
+    if (n < 0) {
+       if (errno != ENOBUFS && errno != EWOULDBLOCK) {
+           setcommandmode();
+           perror(hostname);
+           (void)NetClose(net);
+           ring_clear_mark(&netoring);
+           longjmp(peerdied, -1);
+           /*NOTREACHED*/
+       }
+       n = 0;
+    }
+    if (netdata && n) {
+       Dump('>', netoring.consume, n);
+    }
+    if (n) {
+       ring_consumed(&netoring, n);
+       /*
+        * If we sent all, and more to send, then recurse to pick
+        * up the other half.
+        */
+       if ((n1 == n) && ring_full_consecutive(&netoring)) {
+           (void) netflush();
+       }
+       return 1;
+    } else {
+       return 0;
+    }
+}
diff --git a/telnet.tproj/ring.c b/telnet.tproj/ring.c
new file mode 100644 (file)
index 0000000..6506ae1
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)ring.c     8.2 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+/*
+ * This defines a structure for a ring buffer.
+ *
+ * The circular buffer has two parts:
+ *(((
+ *     full:   [consume, supply)
+ *     empty:  [supply, consume)
+ *]]]
+ *
+ */
+
+#include       <stdio.h>
+#include       <errno.h>
+
+#ifdef size_t
+#undef size_t
+#endif
+
+#include       <sys/types.h>
+#ifndef        FILIO_H
+#include       <sys/ioctl.h>
+#endif
+#include       <sys/socket.h>
+
+#include       "ring.h"
+#include       "general.h"
+
+/* Internal macros */
+
+#if    !defined(MIN)
+#define        MIN(a,b)        (((a)<(b))? (a):(b))
+#endif /* !defined(MIN) */
+
+#define        ring_subtract(d,a,b)    (((a)-(b) >= 0)? \
+                                       (a)-(b): (((a)-(b))+(d)->size))
+
+#define        ring_increment(d,a,c)   (((a)+(c) < (d)->top)? \
+                                       (a)+(c) : (((a)+(c))-(d)->size))
+
+#define        ring_decrement(d,a,c)   (((a)-(c) >= (d)->bottom)? \
+                                       (a)-(c) : (((a)-(c))-(d)->size))
+
+
+/*
+ * The following is a clock, used to determine full, empty, etc.
+ *
+ * There is some trickiness here.  Since the ring buffers are initialized
+ * to ZERO on allocation, we need to make sure, when interpreting the
+ * clock, that when the times are EQUAL, then the buffer is FULL.
+ */
+static u_long ring_clock = 0;
+
+
+#define        ring_empty(d) (((d)->consume == (d)->supply) && \
+                               ((d)->consumetime >= (d)->supplytime))
+#define        ring_full(d) (((d)->supply == (d)->consume) && \
+                               ((d)->supplytime > (d)->consumetime))
+
+
+
+
+
+/* Buffer state transition routines */
+
+    ring_init(ring, buffer, count)
+Ring *ring;
+    unsigned char *buffer;
+    int count;
+{
+    memset((char *)ring, 0, sizeof *ring);
+
+    ring->size = count;
+
+    ring->supply = ring->consume = ring->bottom = buffer;
+
+    ring->top = ring->bottom+ring->size;
+
+#ifdef ENCRYPTION
+    ring->clearto = 0;
+#endif /* ENCRYPTION */
+
+    return 1;
+}
+
+/* Mark routines */
+
+/*
+ * Mark the most recently supplied byte.
+ */
+
+    void
+ring_mark(ring)
+    Ring *ring;
+{
+    ring->mark = ring_decrement(ring, ring->supply, 1);
+}
+
+/*
+ * Is the ring pointing to the mark?
+ */
+
+    int
+ring_at_mark(ring)
+    Ring *ring;
+{
+    if (ring->mark == ring->consume) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+/*
+ * Clear any mark set on the ring.
+ */
+
+    void
+ring_clear_mark(ring)
+    Ring *ring;
+{
+    ring->mark = 0;
+}
+
+/*
+ * Add characters from current segment to ring buffer.
+ */
+    void
+ring_supplied(ring, count)
+    Ring *ring;
+    int count;
+{
+    ring->supply = ring_increment(ring, ring->supply, count);
+    ring->supplytime = ++ring_clock;
+}
+
+/*
+ * We have just consumed "c" bytes.
+ */
+    void
+ring_consumed(ring, count)
+    Ring *ring;
+    int count;
+{
+    if (count == 0)    /* don't update anything */
+       return;
+
+    if (ring->mark &&
+               (ring_subtract(ring, ring->mark, ring->consume) < count)) {
+       ring->mark = 0;
+    }
+#ifdef ENCRYPTION
+    if (ring->consume < ring->clearto &&
+               ring->clearto <= ring->consume + count)
+       ring->clearto = 0;
+    else if (ring->consume + count > ring->top &&
+               ring->bottom <= ring->clearto &&
+               ring->bottom + ((ring->consume + count) - ring->top))
+       ring->clearto = 0;
+#endif /* ENCRYPTION */
+    ring->consume = ring_increment(ring, ring->consume, count);
+    ring->consumetime = ++ring_clock;
+    /*
+     * Try to encourage "ring_empty_consecutive()" to be large.
+     */
+    if (ring_empty(ring)) {
+       ring->consume = ring->supply = ring->bottom;
+    }
+}
+
+
+
+/* Buffer state query routines */
+
+
+/* Number of bytes that may be supplied */
+    int
+ring_empty_count(ring)
+    Ring *ring;
+{
+    if (ring_empty(ring)) {    /* if empty */
+           return ring->size;
+    } else {
+       return ring_subtract(ring, ring->consume, ring->supply);
+    }
+}
+
+/* number of CONSECUTIVE bytes that may be supplied */
+    int
+ring_empty_consecutive(ring)
+    Ring *ring;
+{
+    if ((ring->consume < ring->supply) || ring_empty(ring)) {
+                           /*
+                            * if consume is "below" supply, or empty, then
+                            * return distance to the top
+                            */
+       return ring_subtract(ring, ring->top, ring->supply);
+    } else {
+                                   /*
+                                    * else, return what we may.
+                                    */
+       return ring_subtract(ring, ring->consume, ring->supply);
+    }
+}
+
+/* Return the number of bytes that are available for consuming
+ * (but don't give more than enough to get to cross over set mark)
+ */
+
+    int
+ring_full_count(ring)
+    Ring *ring;
+{
+    if ((ring->mark == 0) || (ring->mark == ring->consume)) {
+       if (ring_full(ring)) {
+           return ring->size;  /* nothing consumed, but full */
+       } else {
+           return ring_subtract(ring, ring->supply, ring->consume);
+       }
+    } else {
+       return ring_subtract(ring, ring->mark, ring->consume);
+    }
+}
+
+/*
+ * Return the number of CONSECUTIVE bytes available for consuming.
+ * However, don't return more than enough to cross over set mark.
+ */
+    int
+ring_full_consecutive(ring)
+    Ring *ring;
+{
+    if ((ring->mark == 0) || (ring->mark == ring->consume)) {
+       if ((ring->supply < ring->consume) || ring_full(ring)) {
+           return ring_subtract(ring, ring->top, ring->consume);
+       } else {
+           return ring_subtract(ring, ring->supply, ring->consume);
+       }
+    } else {
+       if (ring->mark < ring->consume) {
+           return ring_subtract(ring, ring->top, ring->consume);
+       } else {        /* Else, distance to mark */
+           return ring_subtract(ring, ring->mark, ring->consume);
+       }
+    }
+}
+
+/*
+ * Move data into the "supply" portion of of the ring buffer.
+ */
+    void
+ring_supply_data(ring, buffer, count)
+    Ring *ring;
+    unsigned char *buffer;
+    int count;
+{
+    int i;
+
+    while (count) {
+       i = MIN(count, ring_empty_consecutive(ring));
+       memmove(ring->supply, buffer, i);
+       ring_supplied(ring, i);
+       count -= i;
+       buffer += i;
+    }
+}
+
+#ifdef notdef
+
+/*
+ * Move data from the "consume" portion of the ring buffer
+ */
+    void
+ring_consume_data(ring, buffer, count)
+    Ring *ring;
+    unsigned char *buffer;
+    int count;
+{
+    int i;
+
+    while (count) {
+       i = MIN(count, ring_full_consecutive(ring));
+       memmove(buffer, ring->consume, i);
+       ring_consumed(ring, i);
+       count -= i;
+       buffer += i;
+    }
+}
+#endif
+
+#ifdef ENCRYPTION
+    void
+ring_encrypt(ring, encryptor)
+    Ring *ring;
+    void (*encryptor)();
+{
+    unsigned char *s, *c;
+
+    if (ring_empty(ring) || ring->clearto == ring->supply)
+       return;
+
+    if (!(c = ring->clearto))
+       c = ring->consume;
+
+    s = ring->supply;
+
+    if (s <= c) {
+       (*encryptor)(c, ring->top - c);
+       (*encryptor)(ring->bottom, s - ring->bottom);
+    } else
+       (*encryptor)(c, s - c);
+
+    ring->clearto = ring->supply;
+}
+
+    void
+ring_clearto(ring)
+    Ring *ring;
+{
+    if (!ring_empty(ring))
+       ring->clearto = ring->supply;
+    else
+       ring->clearto = 0;
+}
+#endif /* ENCRYPTION */
diff --git a/telnet.tproj/ring.h b/telnet.tproj/ring.h
new file mode 100644 (file)
index 0000000..a9ef843
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ring.h      8.1 (Berkeley) 6/6/93
+ */
+
+#if defined(P)
+# undef P
+#endif
+
+#if defined(__STDC__) || defined(LINT_ARGS)
+# define       P(x)    x
+#else
+# define       P(x)    ()
+#endif
+
+/*
+ * This defines a structure for a ring buffer.
+ *
+ * The circular buffer has two parts:
+ *(((
+ *     full:   [consume, supply)
+ *     empty:  [supply, consume)
+ *]]]
+ *
+ */
+typedef struct {
+    unsigned char      *consume,       /* where data comes out of */
+                       *supply,        /* where data comes in to */
+                       *bottom,        /* lowest address in buffer */
+                       *top,           /* highest address+1 in buffer */
+                       *mark;          /* marker (user defined) */
+#ifdef ENCRYPTION
+    unsigned char      *clearto;       /* Data to this point is clear text */
+    unsigned char      *encryyptedto;  /* Data is encrypted to here */
+#endif /* ENCRYPTION */
+    int                size;           /* size in bytes of buffer */
+    u_long     consumetime,    /* help us keep straight full, empty, etc. */
+               supplytime;
+} Ring;
+
+/* Here are some functions and macros to deal with the ring buffer */
+
+/* Initialization routine */
+extern int
+       ring_init P((Ring *ring, unsigned char *buffer, int count));
+
+/* Data movement routines */
+extern void
+       ring_supply_data P((Ring *ring, unsigned char *buffer, int count));
+#ifdef notdef
+extern void
+       ring_consume_data P((Ring *ring, unsigned char *buffer, int count));
+#endif
+
+/* Buffer state transition routines */
+extern void
+       ring_supplied P((Ring *ring, int count)),
+       ring_consumed P((Ring *ring, int count));
+
+/* Buffer state query routines */
+extern int
+       ring_empty_count P((Ring *ring)),
+       ring_empty_consecutive P((Ring *ring)),
+       ring_full_count P((Ring *ring)),
+       ring_full_consecutive P((Ring *ring));
+
+#ifdef ENCRYPTION
+extern void
+       ring_encrypt P((Ring *ring, void (*func)())),
+       ring_clearto P((Ring *ring));
+#endif /* ENCRYPTION */
+
+extern void
+    ring_clear_mark(),
+    ring_mark();
diff --git a/telnet.tproj/sys_bsd.c b/telnet.tproj/sys_bsd.c
new file mode 100644 (file)
index 0000000..8455d4d
--- /dev/null
@@ -0,0 +1,1243 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)sys_bsd.c  8.4 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+/*
+ * The following routines try to encapsulate what is system dependent
+ * (at least between 4.x and dos) which is used in telnet.c.
+ */
+
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <errno.h>
+#include <arpa/telnet.h>
+
+#include "ring.h"
+
+#include "fdset.h"
+
+#include "defines.h"
+#include "externs.h"
+#include "types.h"
+
+#if    defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO))
+#define        SIG_FUNC_RET    void
+#else
+#define        SIG_FUNC_RET    int
+#endif
+
+#ifdef SIGINFO
+extern SIG_FUNC_RET ayt_status();
+#endif
+
+int
+       tout,                   /* Output file descriptor */
+       tin,                    /* Input file descriptor */
+       net;
+
+#ifndef        USE_TERMIO
+struct tchars otc = { 0 }, ntc = { 0 };
+struct ltchars oltc = { 0 }, nltc = { 0 };
+struct sgttyb ottyb = { 0 }, nttyb = { 0 };
+int    olmode = 0;
+# define cfgetispeed(ptr)      (ptr)->sg_ispeed
+# define cfgetospeed(ptr)      (ptr)->sg_ospeed
+# define old_tc ottyb
+
+#else  /* USE_TERMIO */
+struct termio old_tc = { 0 };
+extern struct termio new_tc;
+
+# ifndef       TCSANOW
+#  ifdef TCSETS
+#   define     TCSANOW         TCSETS
+#   define     TCSADRAIN       TCSETSW
+#   define     tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
+#  else
+#   ifdef TCSETA
+#    define    TCSANOW         TCSETA
+#    define    TCSADRAIN       TCSETAW
+#    define    tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
+#   else
+#    define    TCSANOW         TIOCSETA
+#    define    TCSADRAIN       TIOCSETAW
+#    define    tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
+#   endif
+#  endif
+#  define      tcsetattr(f, a, t) ioctl(f, a, (char *)t)
+#  define      cfgetospeed(ptr)        ((ptr)->c_cflag&CBAUD)
+#  ifdef CIBAUD
+#   define     cfgetispeed(ptr)        (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
+#  else
+#   define     cfgetispeed(ptr)        cfgetospeed(ptr)
+#  endif
+# endif /* TCSANOW */
+# ifdef        sysV88
+# define TIOCFLUSH TC_PX_DRAIN
+# endif
+#endif /* USE_TERMIO */
+
+static fd_set ibits, obits, xbits;
+
+
+    void
+init_sys()
+{
+    tout = fileno(stdout);
+    tin = fileno(stdin);
+    FD_ZERO(&ibits);
+    FD_ZERO(&obits);
+    FD_ZERO(&xbits);
+
+    errno = 0;
+}
+
+
+    int
+TerminalWrite(buf, n)
+    char *buf;
+    int  n;
+{
+    return write(tout, buf, n);
+}
+
+    int
+TerminalRead(buf, n)
+    char *buf;
+    int  n;
+{
+    return read(tin, buf, n);
+}
+
+/*
+ *
+ */
+
+    int
+TerminalAutoFlush()
+{
+#if    defined(LNOFLSH)
+    int flush;
+
+    ioctl(0, TIOCLGET, (char *)&flush);
+    return !(flush&LNOFLSH);   /* if LNOFLSH, no autoflush */
+#else  /* LNOFLSH */
+    return 1;
+#endif /* LNOFLSH */
+}
+
+#ifdef KLUDGELINEMODE
+extern int kludgelinemode;
+#endif
+/*
+ * TerminalSpecialChars()
+ *
+ * Look at an input character to see if it is a special character
+ * and decide what to do.
+ *
+ * Output:
+ *
+ *     0       Don't add this character.
+ *     1       Do add this character
+ */
+
+extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
+
+    int
+TerminalSpecialChars(c)
+    int        c;
+{
+    if (c == termIntChar) {
+       intp();
+       return 0;
+    } else if (c == termQuitChar) {
+#ifdef KLUDGELINEMODE
+       if (kludgelinemode)
+           sendbrk();
+       else
+#endif
+           sendabort();
+       return 0;
+    } else if (c == termEofChar) {
+       if (my_want_state_is_will(TELOPT_LINEMODE)) {
+           sendeof();
+           return 0;
+       }
+       return 1;
+    } else if (c == termSuspChar) {
+       sendsusp();
+       return(0);
+    } else if (c == termFlushChar) {
+       xmitAO();               /* Transmit Abort Output */
+       return 0;
+    } else if (!MODE_LOCAL_CHARS(globalmode)) {
+       if (c == termKillChar) {
+           xmitEL();
+           return 0;
+       } else if (c == termEraseChar) {
+           xmitEC();           /* Transmit Erase Character */
+           return 0;
+       }
+    }
+    return 1;
+}
+
+
+/*
+ * Flush output to the terminal
+ */
+
+    void
+TerminalFlushOutput()
+{
+#ifdef TIOCFLUSH
+    (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
+#else
+    (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
+#endif
+}
+
+    void
+TerminalSaveState()
+{
+#ifndef        USE_TERMIO
+    ioctl(0, TIOCGETP, (char *)&ottyb);
+    ioctl(0, TIOCGETC, (char *)&otc);
+    ioctl(0, TIOCGLTC, (char *)&oltc);
+    ioctl(0, TIOCLGET, (char *)&olmode);
+
+    ntc = otc;
+    nltc = oltc;
+    nttyb = ottyb;
+
+#else  /* USE_TERMIO */
+    tcgetattr(0, &old_tc);
+
+    new_tc = old_tc;
+
+#ifndef        VDISCARD
+    termFlushChar = CONTROL('O');
+#endif
+#ifndef        VWERASE
+    termWerasChar = CONTROL('W');
+#endif
+#ifndef        VREPRINT
+    termRprntChar = CONTROL('R');
+#endif
+#ifndef        VLNEXT
+    termLiteralNextChar = CONTROL('V');
+#endif
+#ifndef        VSTART
+    termStartChar = CONTROL('Q');
+#endif
+#ifndef        VSTOP
+    termStopChar = CONTROL('S');
+#endif
+#ifndef        VSTATUS
+    termAytChar = CONTROL('T');
+#endif
+#endif /* USE_TERMIO */
+}
+
+    cc_t *
+tcval(func)
+    register int func;
+{
+    switch(func) {
+    case SLC_IP:       return(&termIntChar);
+    case SLC_ABORT:    return(&termQuitChar);
+    case SLC_EOF:      return(&termEofChar);
+    case SLC_EC:       return(&termEraseChar);
+    case SLC_EL:       return(&termKillChar);
+    case SLC_XON:      return(&termStartChar);
+    case SLC_XOFF:     return(&termStopChar);
+    case SLC_FORW1:    return(&termForw1Char);
+#ifdef USE_TERMIO
+    case SLC_FORW2:    return(&termForw2Char);
+# ifdef        VDISCARD
+    case SLC_AO:       return(&termFlushChar);
+# endif
+# ifdef        VSUSP
+    case SLC_SUSP:     return(&termSuspChar);
+# endif
+# ifdef        VWERASE
+    case SLC_EW:       return(&termWerasChar);
+# endif
+# ifdef        VREPRINT
+    case SLC_RP:       return(&termRprntChar);
+# endif
+# ifdef        VLNEXT
+    case SLC_LNEXT:    return(&termLiteralNextChar);
+# endif
+# ifdef        VSTATUS
+    case SLC_AYT:      return(&termAytChar);
+# endif
+#endif
+
+    case SLC_SYNCH:
+    case SLC_BRK:
+    case SLC_EOR:
+    default:
+       return((cc_t *)0);
+    }
+}
+
+    void
+TerminalDefaultChars()
+{
+#ifndef        USE_TERMIO
+    ntc = otc;
+    nltc = oltc;
+    nttyb.sg_kill = ottyb.sg_kill;
+    nttyb.sg_erase = ottyb.sg_erase;
+#else  /* USE_TERMIO */
+    memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
+# ifndef       VDISCARD
+    termFlushChar = CONTROL('O');
+# endif
+# ifndef       VWERASE
+    termWerasChar = CONTROL('W');
+# endif
+# ifndef       VREPRINT
+    termRprntChar = CONTROL('R');
+# endif
+# ifndef       VLNEXT
+    termLiteralNextChar = CONTROL('V');
+# endif
+# ifndef       VSTART
+    termStartChar = CONTROL('Q');
+# endif
+# ifndef       VSTOP
+    termStopChar = CONTROL('S');
+# endif
+# ifndef       VSTATUS
+    termAytChar = CONTROL('T');
+# endif
+#endif /* USE_TERMIO */
+}
+
+#ifdef notdef
+void
+TerminalRestoreState()
+{
+}
+#endif
+
+/*
+ * TerminalNewMode - set up terminal to a specific mode.
+ *     MODE_ECHO: do local terminal echo
+ *     MODE_FLOW: do local flow control
+ *     MODE_TRAPSIG: do local mapping to TELNET IAC sequences
+ *     MODE_EDIT: do local line editing
+ *
+ *     Command mode:
+ *             MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
+ *             local echo
+ *             local editing
+ *             local xon/xoff
+ *             local signal mapping
+ *
+ *     Linemode:
+ *             local/no editing
+ *     Both Linemode and Single Character mode:
+ *             local/remote echo
+ *             local/no xon/xoff
+ *             local/no signal mapping
+ */
+
+
+    void
+TerminalNewMode(f)
+    register int f;
+{
+    static int prevmode = 0;
+#ifndef        USE_TERMIO
+    struct tchars tc;
+    struct ltchars ltc;
+    struct sgttyb sb;
+    int lmode;
+#else  /* USE_TERMIO */
+    struct termio tmp_tc;
+#endif /* USE_TERMIO */
+    int onoff;
+    int old;
+    cc_t esc;
+
+    globalmode = f&~MODE_FORCE;
+    if (prevmode == f)
+       return;
+
+    /*
+     * Write any outstanding data before switching modes
+     * ttyflush() returns 0 only when there is no more data
+     * left to write out, it returns -1 if it couldn't do
+     * anything at all, otherwise it returns 1 + the number
+     * of characters left to write.
+#ifndef        USE_TERMIO
+     * We would really like ask the kernel to wait for the output
+     * to drain, like we can do with the TCSADRAIN, but we don't have
+     * that option.  The only ioctl that waits for the output to
+     * drain, TIOCSETP, also flushes the input queue, which is NOT
+     * what we want (TIOCSETP is like TCSADFLUSH).
+#endif
+     */
+    old = ttyflush(SYNCHing|flushout);
+    if (old < 0 || old > 1) {
+#ifdef USE_TERMIO
+       tcgetattr(tin, &tmp_tc);
+#endif /* USE_TERMIO */
+       do {
+           /*
+            * Wait for data to drain, then flush again.
+            */
+#ifdef USE_TERMIO
+           tcsetattr(tin, TCSADRAIN, &tmp_tc);
+#endif /* USE_TERMIO */
+           old = ttyflush(SYNCHing|flushout);
+       } while (old < 0 || old > 1);
+    }
+
+    old = prevmode;
+    prevmode = f&~MODE_FORCE;
+#ifndef        USE_TERMIO
+    sb = nttyb;
+    tc = ntc;
+    ltc = nltc;
+    lmode = olmode;
+#else
+    tmp_tc = new_tc;
+#endif
+
+    if (f&MODE_ECHO) {
+#ifndef        USE_TERMIO
+       sb.sg_flags |= ECHO;
+#else
+       tmp_tc.c_lflag |= ECHO;
+       tmp_tc.c_oflag |= ONLCR;
+       if (crlf)
+               tmp_tc.c_iflag |= ICRNL;
+#endif
+    } else {
+#ifndef        USE_TERMIO
+       sb.sg_flags &= ~ECHO;
+#else
+       tmp_tc.c_lflag &= ~ECHO;
+       tmp_tc.c_oflag &= ~ONLCR;
+# ifdef notdef
+       if (crlf)
+               tmp_tc.c_iflag &= ~ICRNL;
+# endif
+#endif
+    }
+
+    if ((f&MODE_FLOW) == 0) {
+#ifndef        USE_TERMIO
+       tc.t_startc = _POSIX_VDISABLE;
+       tc.t_stopc = _POSIX_VDISABLE;
+#else
+       tmp_tc.c_iflag &= ~(IXOFF|IXON);        /* Leave the IXANY bit alone */
+    } else {
+       if (restartany < 0) {
+               tmp_tc.c_iflag |= IXOFF|IXON;   /* Leave the IXANY bit alone */
+       } else if (restartany > 0) {
+               tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
+       } else {
+               tmp_tc.c_iflag |= IXOFF|IXON;
+               tmp_tc.c_iflag &= ~IXANY;
+       }
+#endif
+    }
+
+    if ((f&MODE_TRAPSIG) == 0) {
+#ifndef        USE_TERMIO
+       tc.t_intrc = _POSIX_VDISABLE;
+       tc.t_quitc = _POSIX_VDISABLE;
+       tc.t_eofc = _POSIX_VDISABLE;
+       ltc.t_suspc = _POSIX_VDISABLE;
+       ltc.t_dsuspc = _POSIX_VDISABLE;
+#else
+       tmp_tc.c_lflag &= ~ISIG;
+#endif
+       localchars = 0;
+    } else {
+#ifdef USE_TERMIO
+       tmp_tc.c_lflag |= ISIG;
+#endif
+       localchars = 1;
+    }
+
+    if (f&MODE_EDIT) {
+#ifndef        USE_TERMIO
+       sb.sg_flags &= ~CBREAK;
+       sb.sg_flags |= CRMOD;
+#else
+       tmp_tc.c_lflag |= ICANON;
+#endif
+    } else {
+#ifndef        USE_TERMIO
+       sb.sg_flags |= CBREAK;
+       if (f&MODE_ECHO)
+           sb.sg_flags |= CRMOD;
+       else
+           sb.sg_flags &= ~CRMOD;
+#else
+       tmp_tc.c_lflag &= ~ICANON;
+       tmp_tc.c_iflag &= ~ICRNL;
+       tmp_tc.c_cc[VMIN] = 1;
+       tmp_tc.c_cc[VTIME] = 0;
+#endif
+    }
+
+    if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
+#ifndef        USE_TERMIO
+       ltc.t_lnextc = _POSIX_VDISABLE;
+#else
+# ifdef VLNEXT
+       tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
+# endif
+#endif
+    }
+
+    if (f&MODE_SOFT_TAB) {
+#ifndef USE_TERMIO
+       sb.sg_flags |= XTABS;
+#else
+# ifdef        OXTABS
+       tmp_tc.c_oflag |= OXTABS;
+# endif
+# ifdef        TABDLY
+       tmp_tc.c_oflag &= ~TABDLY;
+       tmp_tc.c_oflag |= TAB3;
+# endif
+#endif
+    } else {
+#ifndef USE_TERMIO
+       sb.sg_flags &= ~XTABS;
+#else
+# ifdef        OXTABS
+       tmp_tc.c_oflag &= ~OXTABS;
+# endif
+# ifdef        TABDLY
+       tmp_tc.c_oflag &= ~TABDLY;
+# endif
+#endif
+    }
+
+    if (f&MODE_LIT_ECHO) {
+#ifndef USE_TERMIO
+       lmode &= ~LCTLECH;
+#else
+# ifdef        ECHOCTL
+       tmp_tc.c_lflag &= ~ECHOCTL;
+# endif
+#endif
+    } else {
+#ifndef USE_TERMIO
+       lmode |= LCTLECH;
+#else
+# ifdef        ECHOCTL
+       tmp_tc.c_lflag |= ECHOCTL;
+# endif
+#endif
+    }
+
+    if (f == -1) {
+       onoff = 0;
+    } else {
+#ifndef        USE_TERMIO
+       if (f & MODE_OUTBIN)
+               lmode |= LLITOUT;
+       else
+               lmode &= ~LLITOUT;
+
+       if (f & MODE_INBIN)
+               lmode |= LPASS8;
+       else
+               lmode &= ~LPASS8;
+#else
+       if (f & MODE_INBIN)
+               tmp_tc.c_iflag &= ~ISTRIP;
+       else
+               tmp_tc.c_iflag |= ISTRIP;
+       if (f & MODE_OUTBIN) {
+               tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+               tmp_tc.c_cflag |= CS8;
+               tmp_tc.c_oflag &= ~OPOST;
+       } else {
+               tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+               tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
+               tmp_tc.c_oflag |= OPOST;
+       }
+#endif
+       onoff = 1;
+    }
+
+    if (f != -1) {
+#ifdef SIGTSTP
+       SIG_FUNC_RET susp();
+#endif /* SIGTSTP */
+#ifdef SIGINFO
+       SIG_FUNC_RET ayt();
+#endif
+
+#ifdef SIGTSTP
+       (void) signal(SIGTSTP, susp);
+#endif /* SIGTSTP */
+#ifdef SIGINFO
+       (void) signal(SIGINFO, ayt);
+#endif
+#if    defined(USE_TERMIO) && defined(NOKERNINFO)
+       tmp_tc.c_lflag |= NOKERNINFO;
+#endif
+       /*
+        * We don't want to process ^Y here.  It's just another
+        * character that we'll pass on to the back end.  It has
+        * to process it because it will be processed when the
+        * user attempts to read it, not when we send it.
+        */
+#ifndef        USE_TERMIO
+       ltc.t_dsuspc = _POSIX_VDISABLE;
+#else
+# ifdef        VDSUSP
+       tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
+# endif
+#endif
+#ifdef USE_TERMIO
+       /*
+        * If the VEOL character is already set, then use VEOL2,
+        * otherwise use VEOL.
+        */
+       esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
+       if ((tmp_tc.c_cc[VEOL] != esc)
+# ifdef        VEOL2
+           && (tmp_tc.c_cc[VEOL2] != esc)
+# endif
+           ) {
+               if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
+                   tmp_tc.c_cc[VEOL] = esc;
+# ifdef        VEOL2
+               else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
+                   tmp_tc.c_cc[VEOL2] = esc;
+# endif
+       }
+#else
+       if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
+               tc.t_brkc = esc;
+#endif
+    } else {
+#ifdef SIGINFO
+       SIG_FUNC_RET ayt_status();
+
+       (void) signal(SIGINFO, ayt_status);
+#endif
+#ifdef SIGTSTP
+       (void) signal(SIGTSTP, SIG_DFL);
+# ifndef SOLARIS
+       (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
+# else SOLARIS
+       (void) sigrelse(SIGTSTP);
+# endif        SOLARIS
+#endif /* SIGTSTP */
+#ifndef USE_TERMIO
+       ltc = oltc;
+       tc = otc;
+       sb = ottyb;
+       lmode = olmode;
+#else
+       tmp_tc = old_tc;
+#endif
+    }
+#ifndef USE_TERMIO
+    ioctl(tin, TIOCLSET, (char *)&lmode);
+    ioctl(tin, TIOCSLTC, (char *)&ltc);
+    ioctl(tin, TIOCSETC, (char *)&tc);
+    ioctl(tin, TIOCSETN, (char *)&sb);
+#else
+    if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
+       tcsetattr(tin, TCSANOW, &tmp_tc);
+#endif
+
+#if    (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
+# if   !defined(sysV88)
+    ioctl(tin, FIONBIO, (char *)&onoff);
+    ioctl(tout, FIONBIO, (char *)&onoff);
+# endif
+#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
+#if    defined(TN3270)
+    if (noasynchtty == 0) {
+       ioctl(tin, FIOASYNC, (char *)&onoff);
+    }
+#endif /* defined(TN3270) */
+
+}
+
+/*
+ * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
+ */
+#if B4800 != 4800
+#define        DECODE_BAUD
+#endif
+
+#ifdef DECODE_BAUD
+#ifndef        B7200
+#define B7200   B4800
+#endif
+
+#ifndef        B14400
+#define B14400  B9600
+#endif
+
+#ifndef        B19200
+# define B19200 B14400
+#endif
+
+#ifndef        B28800
+#define B28800  B19200
+#endif
+
+#ifndef        B38400
+# define B38400 B28800
+#endif
+
+#ifndef B57600
+#define B57600  B38400
+#endif
+
+#ifndef B76800
+#define B76800  B57600
+#endif
+
+#ifndef B115200
+#define B115200 B76800
+#endif
+
+#ifndef B230400
+#define B230400 B115200
+#endif
+
+
+/*
+ * This code assumes that the values B0, B50, B75...
+ * are in ascending order.  They do not have to be
+ * contiguous.
+ */
+struct termspeeds {
+       long speed;
+       long value;
+} termspeeds[] = {
+       { 0,      B0 },      { 50,    B50 },    { 75,     B75 },
+       { 110,    B110 },    { 134,   B134 },   { 150,    B150 },
+       { 200,    B200 },    { 300,   B300 },   { 600,    B600 },
+       { 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
+       { 4800,   B4800 },   { 7200,  B7200 },  { 9600,   B9600 },
+       { 14400,  B14400 },  { 19200, B19200 }, { 28800,  B28800 },
+       { 38400,  B38400 },  { 57600, B57600 }, { 115200, B115200 },
+       { 230400, B230400 }, { -1,    B230400 }
+};
+#endif /* DECODE_BAUD */
+
+    void
+TerminalSpeeds(ispeed, ospeed)
+    long *ispeed;
+    long *ospeed;
+{
+#ifdef DECODE_BAUD
+    register struct termspeeds *tp;
+#endif /* DECODE_BAUD */
+    register long in, out;
+
+    out = cfgetospeed(&old_tc);
+    in = cfgetispeed(&old_tc);
+    if (in == 0)
+       in = out;
+
+#ifdef DECODE_BAUD
+    tp = termspeeds;
+    while ((tp->speed != -1) && (tp->value < in))
+       tp++;
+    *ispeed = tp->speed;
+
+    tp = termspeeds;
+    while ((tp->speed != -1) && (tp->value < out))
+       tp++;
+    *ospeed = tp->speed;
+#else  /* DECODE_BAUD */
+       *ispeed = in;
+       *ospeed = out;
+#endif /* DECODE_BAUD */
+}
+
+    int
+TerminalWindowSize(rows, cols)
+    long *rows, *cols;
+{
+#ifdef TIOCGWINSZ
+    struct winsize ws;
+
+    if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
+       *rows = ws.ws_row;
+       *cols = ws.ws_col;
+       return 1;
+    }
+#endif /* TIOCGWINSZ */
+    return 0;
+}
+
+    int
+NetClose(fd)
+    int        fd;
+{
+    return close(fd);
+}
+
+
+    void
+NetNonblockingIO(fd, onoff)
+    int fd;
+    int onoff;
+{
+    ioctl(fd, FIONBIO, (char *)&onoff);
+}
+
+#if    defined(TN3270)
+    void
+NetSigIO(fd, onoff)
+    int fd;
+    int onoff;
+{
+    ioctl(fd, FIOASYNC, (char *)&onoff);       /* hear about input */
+}
+
+    void
+NetSetPgrp(fd)
+    int fd;
+{
+    int myPid;
+
+    myPid = getpid();
+    fcntl(fd, F_SETOWN, myPid);
+}
+#endif /*defined(TN3270)*/
+\f
+/*
+ * Various signal handling routines.
+ */
+
+    /* ARGSUSED */
+    SIG_FUNC_RET
+deadpeer(sig)
+    int sig;
+{
+       setcommandmode();
+       longjmp(peerdied, -1);
+}
+
+    /* ARGSUSED */
+    SIG_FUNC_RET
+intr(sig)
+    int sig;
+{
+    if (localchars) {
+       intp();
+       return;
+    }
+    setcommandmode();
+    longjmp(toplevel, -1);
+}
+
+    /* ARGSUSED */
+    SIG_FUNC_RET
+intr2(sig)
+    int sig;
+{
+    if (localchars) {
+#ifdef KLUDGELINEMODE
+       if (kludgelinemode)
+           sendbrk();
+       else
+#endif
+           sendabort();
+       return;
+    }
+}
+
+#ifdef SIGTSTP
+    /* ARGSUSED */
+    SIG_FUNC_RET
+susp(sig)
+    int sig;
+{
+    if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
+       return;
+    if (localchars)
+       sendsusp();
+}
+#endif
+
+#ifdef SIGWINCH
+    /* ARGSUSED */
+    SIG_FUNC_RET
+sendwin(sig)
+    int sig;
+{
+    if (connected) {
+       sendnaws();
+    }
+}
+#endif
+
+#ifdef SIGINFO
+    /* ARGSUSED */
+    SIG_FUNC_RET
+ayt(sig)
+    int sig;
+{
+    if (connected)
+       sendayt();
+    else
+       ayt_status();
+}
+#endif
+
+\f
+    void
+sys_telnet_init()
+{
+    (void) signal(SIGINT, intr);
+    (void) signal(SIGQUIT, intr2);
+    (void) signal(SIGPIPE, deadpeer);
+#ifdef SIGWINCH
+    (void) signal(SIGWINCH, sendwin);
+#endif
+#ifdef SIGTSTP
+    (void) signal(SIGTSTP, susp);
+#endif
+#ifdef SIGINFO
+    (void) signal(SIGINFO, ayt);
+#endif
+
+    setconnmode(0);
+
+    NetNonblockingIO(net, 1);
+
+#if    defined(TN3270)
+    if (noasynchnet == 0) {                    /* DBX can't handle! */
+       NetSigIO(net, 1);
+       NetSetPgrp(net);
+    }
+#endif /* defined(TN3270) */
+
+#if    defined(SO_OOBINLINE)
+    if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
+       perror("SetSockOpt");
+    }
+#endif /* defined(SO_OOBINLINE) */
+}
+
+/*
+ * Process rings -
+ *
+ *     This routine tries to fill up/empty our various rings.
+ *
+ *     The parameter specifies whether this is a poll operation,
+ *     or a block-until-something-happens operation.
+ *
+ *     The return value is 1 if something happened, 0 if not.
+ */
+
+    int
+process_rings(netin, netout, netex, ttyin, ttyout, poll)
+    int poll;          /* If 0, then block until something to do */
+{
+    register int c;
+               /* One wants to be a bit careful about setting returnValue
+                * to one, since a one implies we did some useful work,
+                * and therefore probably won't be called to block next
+                * time (TN3270 mode only).
+                */
+    int returnValue = 0;
+    static struct timeval TimeValue = { 0 };
+
+    if (netout) {
+       FD_SET(net, &obits);
+    }
+    if (ttyout) {
+       FD_SET(tout, &obits);
+    }
+#if    defined(TN3270)
+    if (ttyin) {
+       FD_SET(tin, &ibits);
+    }
+#else  /* defined(TN3270) */
+    if (ttyin) {
+       FD_SET(tin, &ibits);
+    }
+#endif /* defined(TN3270) */
+#if    defined(TN3270)
+    if (netin) {
+       FD_SET(net, &ibits);
+    }
+#   else /* !defined(TN3270) */
+    if (netin) {
+       FD_SET(net, &ibits);
+    }
+#   endif /* !defined(TN3270) */
+    if (netex) {
+       FD_SET(net, &xbits);
+    }
+    if ((c = select(16, &ibits, &obits, &xbits,
+                       (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
+       if (c == -1) {
+                   /*
+                    * we can get EINTR if we are in line mode,
+                    * and the user does an escape (TSTP), or
+                    * some other signal generator.
+                    */
+           if (errno == EINTR) {
+               return 0;
+           }
+#          if defined(TN3270)
+                   /*
+                    * we can get EBADF if we were in transparent
+                    * mode, and the transcom process died.
+                   */
+           if (errno == EBADF) {
+                       /*
+                        * zero the bits (even though kernel does it)
+                        * to make sure we are selecting on the right
+                        * ones.
+                       */
+               FD_ZERO(&ibits);
+               FD_ZERO(&obits);
+               FD_ZERO(&xbits);
+               return 0;
+           }
+#          endif /* defined(TN3270) */
+                   /* I don't like this, does it ever happen? */
+           printf("sleep(5) from telnet, after select\r\n");
+           sleep(5);
+       }
+       return 0;
+    }
+
+    /*
+     * Any urgent data?
+     */
+    if (FD_ISSET(net, &xbits)) {
+       FD_CLR(net, &xbits);
+       SYNCHing = 1;
+       (void) ttyflush(1);     /* flush already enqueued data */
+    }
+
+    /*
+     * Something to read from the network...
+     */
+    if (FD_ISSET(net, &ibits)) {
+       int canread;
+
+       FD_CLR(net, &ibits);
+       canread = ring_empty_consecutive(&netiring);
+#if    !defined(SO_OOBINLINE)
+           /*
+            * In 4.2 (and some early 4.3) systems, the
+            * OOB indication and data handling in the kernel
+            * is such that if two separate TCP Urgent requests
+            * come in, one byte of TCP data will be overlaid.
+            * This is fatal for Telnet, but we try to live
+            * with it.
+            *
+            * In addition, in 4.2 (and...), a special protocol
+            * is needed to pick up the TCP Urgent data in
+            * the correct sequence.
+            *
+            * What we do is:  if we think we are in urgent
+            * mode, we look to see if we are "at the mark".
+            * If we are, we do an OOB receive.  If we run
+            * this twice, we will do the OOB receive twice,
+            * but the second will fail, since the second
+            * time we were "at the mark", but there wasn't
+            * any data there (the kernel doesn't reset
+            * "at the mark" until we do a normal read).
+            * Once we've read the OOB data, we go ahead
+            * and do normal reads.
+            *
+            * There is also another problem, which is that
+            * since the OOB byte we read doesn't put us
+            * out of OOB state, and since that byte is most
+            * likely the TELNET DM (data mark), we would
+            * stay in the TELNET SYNCH (SYNCHing) state.
+            * So, clocks to the rescue.  If we've "just"
+            * received a DM, then we test for the
+            * presence of OOB data when the receive OOB
+            * fails (and AFTER we did the normal mode read
+            * to clear "at the mark").
+            */
+       if (SYNCHing) {
+           int atmark;
+           static int bogus_oob = 0, first = 1;
+
+           ioctl(net, SIOCATMARK, (char *)&atmark);
+           if (atmark) {
+               c = recv(net, netiring.supply, canread, MSG_OOB);
+               if ((c == -1) && (errno == EINVAL)) {
+                   c = recv(net, netiring.supply, canread, 0);
+                   if (clocks.didnetreceive < clocks.gotDM) {
+                       SYNCHing = stilloob(net);
+                   }
+               } else if (first && c > 0) {
+                   /*
+                    * Bogosity check.  Systems based on 4.2BSD
+                    * do not return an error if you do a second
+                    * recv(MSG_OOB).  So, we do one.  If it
+                    * succeeds and returns exactly the same
+                    * data, then assume that we are running
+                    * on a broken system and set the bogus_oob
+                    * flag.  (If the data was different, then
+                    * we probably got some valid new data, so
+                    * increment the count...)
+                    */
+                   int i;
+                   i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
+                   if (i == c &&
+                        memcmp(netiring.supply, netiring.supply + c, i) == 0) {
+                       bogus_oob = 1;
+                       first = 0;
+                   } else if (i < 0) {
+                       bogus_oob = 0;
+                       first = 0;
+                   } else
+                       c += i;
+               }
+               if (bogus_oob && c > 0) {
+                   int i;
+                   /*
+                    * Bogosity.  We have to do the read
+                    * to clear the atmark to get out of
+                    * an infinate loop.
+                    */
+                   i = read(net, netiring.supply + c, canread - c);
+                   if (i > 0)
+                       c += i;
+               }
+           } else {
+               c = recv(net, netiring.supply, canread, 0);
+           }
+       } else {
+           c = recv(net, netiring.supply, canread, 0);
+       }
+       settimer(didnetreceive);
+#else  /* !defined(SO_OOBINLINE) */
+       c = recv(net, (char *)netiring.supply, canread, 0);
+#endif /* !defined(SO_OOBINLINE) */
+       if (c < 0 && errno == EWOULDBLOCK) {
+           c = 0;
+       } else if (c <= 0) {
+           return -1;
+       }
+       if (netdata) {
+           Dump('<', netiring.supply, c);
+       }
+       if (c)
+           ring_supplied(&netiring, c);
+       returnValue = 1;
+    }
+
+    /*
+     * Something to read from the tty...
+     */
+    if (FD_ISSET(tin, &ibits)) {
+       FD_CLR(tin, &ibits);
+       c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
+       if (c < 0 && errno == EIO)
+           c = 0;
+       if (c < 0 && errno == EWOULDBLOCK) {
+           c = 0;
+       } else {
+           /* EOF detection for line mode!!!! */
+           if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
+                       /* must be an EOF... */
+               *ttyiring.supply = termEofChar;
+               c = 1;
+           }
+           if (c <= 0) {
+               return -1;
+           }
+           if (termdata) {
+               Dump('<', ttyiring.supply, c);
+           }
+           ring_supplied(&ttyiring, c);
+       }
+       returnValue = 1;                /* did something useful */
+    }
+
+    if (FD_ISSET(net, &obits)) {
+       FD_CLR(net, &obits);
+       returnValue |= netflush();
+    }
+    if (FD_ISSET(tout, &obits)) {
+       FD_CLR(tout, &obits);
+       returnValue |= (ttyflush(SYNCHing|flushout) > 0);
+    }
+
+    return returnValue;
+}
diff --git a/telnet.tproj/telnet.1 b/telnet.tproj/telnet.1
new file mode 100644 (file)
index 0000000..b996fea
--- /dev/null
@@ -0,0 +1,1366 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)telnet.1    8.6 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt TELNET 1
+.Os BSD 4.2
+.Sh NAME
+.Nm telnet
+.Nd user interface to the 
+.Tn TELNET
+protocol
+.Sh SYNOPSIS
+.Nm telnet
+.Op Fl 8EFKLacdfrx
+.Op Fl S Ar tos
+.Op Fl X Ar authtype
+.Op Fl e Ar escapechar
+.Op Fl k Ar realm
+.Op Fl l Ar user
+.Op Fl n Ar tracefile
+.Oo
+.Ar host
+.Op port
+.Oc
+.Sh DESCRIPTION
+The
+.Nm telnet
+command
+is used to communicate with another host using the 
+.Tn TELNET
+protocol.
+If
+.Nm telnet
+is invoked without the
+.Ar host
+argument, it enters command mode,
+indicated by its prompt
+.Pq Nm telnet\&> .
+In this mode, it accepts and executes the commands listed below.
+If it is invoked with arguments, it performs an
+.Ic open
+command with those arguments.
+.Pp
+Options:
+.Bl -tag -width indent
+.It Fl 8
+Specifies an 8-bit data path.  This causes an attempt to
+negotiate the
+.Dv TELNET BINARY
+option on both input and output.
+.It Fl E
+Stops any character from being recognized as an escape character.
+.It Fl F
+If Kerberos V5 authentication is being used, the
+.Fl F
+option allows the local credentials to be forwarded
+to the remote system, including any credentials that
+have already been forwarded into the local environment.
+.It Fl K
+Specifies no automatic login to the remote system.
+.It Fl L
+Specifies an 8-bit data path on output.  This causes the
+BINARY option to be negotiated on output.
+.It Fl S Ar tos
+Sets the IP type-of-service (TOS) option for the telnet
+connection to the value
+.Ar tos,
+which can be a numeric TOS value
+or, on systems that support it, a symbolic
+TOS name found in the /etc/iptos file.
+.It Fl X Ar atype 
+Disables the
+.Ar atype
+type of authentication.
+.It Fl a
+Attempt automatic login.
+Currently, this sends the user name via the
+.Ev USER
+variable
+of the
+.Ev ENVIRON
+option if supported by the remote system.
+The name used is that of the current user as returned by
+.Xr getlogin 2
+if it agrees with the current user ID,
+otherwise it is the name associated with the user ID.
+.It Fl c
+Disables the reading of the user's
+.Pa \&.telnetrc
+file.  (See the
+.Ic toggle skiprc
+command on this man page.)
+.It Fl d
+Sets the initial value of the
+.Ic debug
+toggle to
+.Dv TRUE
+.It Fl e Ar escape char 
+Sets the initial
+.Nm
+.Nm telnet
+escape character to
+.Ar escape char.
+If
+.Ar escape char
+is omitted, then
+there will be no escape character.
+.It Fl f
+If Kerberos V5 authentication is being used, the
+.Fl f
+option allows the local credentials to be forwarded to the remote system.
+.ne 1i
+.It Fl k Ar realm
+If Kerberos authentication is being used, the
+.Fl k
+option requests that telnet obtain tickets for the remote host in
+realm realm instead of the remote host's realm, as determined
+by
+.Xr krb_realmofhost 3 .
+.It Fl l Ar user 
+When connecting to the remote system, if the remote system
+understands the
+.Ev ENVIRON
+option, then
+.Ar user
+will be sent to the remote system as the value for the variable USER.
+This option implies the
+.Fl a
+option.
+This option may also be used with the
+.Ic open
+command.
+.It Fl n Ar tracefile 
+Opens
+.Ar tracefile
+for recording trace information.
+See the
+.Ic set tracefile
+command below.
+.It Fl r
+Specifies a user interface similar to
+.Xr rlogin 1 .
+In this
+mode, the escape character is set to the tilde (~) character,
+unless modified by the -e option.
+.It Fl x
+Turns on encryption of the data stream if possible.  This
+option is not available outside of the United States and
+Canada.
+.It Ar host
+Indicates the official name, an alias, or the Internet address
+of a remote host.
+.It Ar port
+Indicates a port number (address of an application).  If a number is
+not specified, the default
+.Nm telnet
+port is used.
+.El
+.Pp
+When in rlogin mode, a line of the form ~.  disconnects from the
+remote host; ~ is the telnet escape character.
+Similarly, the line ~^Z suspends the telnet session.
+The line ~^] escapes to the normal telnet escape prompt.
+.Pp
+Once a connection has been opened,
+.Nm telnet
+will attempt to enable the
+.Dv TELNET LINEMODE
+option.
+If this fails, then
+.Nm telnet
+will revert to one of two input modes:
+either \*(Lqcharacter at a time\*(Rq
+or \*(Lqold line by line\*(Rq
+depending on what the remote system supports.
+.Pp
+When 
+.Dv LINEMODE
+is enabled, character processing is done on the
+local system, under the control of the remote system.  When input
+editing or character echoing is to be disabled, the remote system
+will relay that information.  The remote system will also relay
+changes to any special characters that happen on the remote
+system, so that they can take effect on the local system.
+.Pp
+In \*(Lqcharacter at a time\*(Rq mode, most
+text typed is immediately sent to the remote host for processing.
+.Pp
+In \*(Lqold line by line\*(Rq mode, all text is echoed locally,
+and (normally) only completed lines are sent to the remote host.
+The \*(Lqlocal echo character\*(Rq (initially \*(Lq^E\*(Rq) may be used
+to turn off and on the local echo
+(this would mostly be used to enter passwords
+without the password being echoed).
+.Pp
+If the 
+.Dv LINEMODE
+option is enabled, or if the
+.Ic localchars
+toggle is
+.Dv TRUE
+(the default for \*(Lqold line by line\*(Lq; see below),
+the user's
+.Ic quit  ,
+.Ic intr ,
+and
+.Ic flush
+characters are trapped locally, and sent as
+.Tn TELNET
+protocol sequences to the remote side.
+If 
+.Dv LINEMODE
+has ever been enabled, then the user's
+.Ic susp
+and
+.Ic eof
+are also sent as
+.Tn TELNET
+protocol sequences,
+and
+.Ic quit
+is sent as a 
+.Dv TELNET ABORT
+instead of 
+.Dv BREAK
+There are options (see
+.Ic toggle
+.Ic autoflush
+and
+.Ic toggle
+.Ic autosynch
+below)
+which cause this action to flush subsequent output to the terminal
+(until the remote host acknowledges the
+.Tn TELNET
+sequence) and flush previous terminal input
+(in the case of
+.Ic quit
+and
+.Ic intr  ) .
+.Pp
+While connected to a remote host,
+.Nm telnet
+command mode may be entered by typing the
+.Nm telnet
+\*(Lqescape character\*(Rq (initially \*(Lq^]\*(Rq).
+When in command mode, the normal terminal editing conventions are available.
+.Pp
+The following
+.Nm telnet
+commands are available.
+Only enough of each command to uniquely identify it need be typed
+(this is also true for arguments to the
+.Ic mode  ,
+.Ic set ,
+.Ic toggle  ,
+.Ic unset ,
+.Ic slc  ,
+.Ic environ ,
+and
+.Ic display
+commands).
+.Pp
+.Bl -tag -width "mode type"
+.It Ic auth Ar argument ... 
+The auth command manipulates the information sent through the
+.Dv TELNET AUTHENTICATE
+option.  Valid arguments for the
+auth command are as follows:
+.Bl -tag -width "disable type"
+.It Ic disable Ar type
+Disables the specified type of authentication.  To
+obtain a list of available types, use the
+.Ic auth disable \&?
+command.
+.It Ic enable Ar type
+Enables the specified type of authentication.  To
+obtain a list of available types, use the
+.Ic auth enable \&?
+command.
+.It Ic status
+Lists the current status of the various types of
+authentication.
+.El
+.It Ic close
+Close a
+.Tn TELNET
+session and return to command mode.
+.It Ic display Ar argument ... 
+Displays all, or some, of the
+.Ic set
+and
+.Ic toggle
+values (see below).
+.It Ic encrypt Ar argument ...
+The encrypt command manipulates the information sent through the
+.Dv TELNET ENCRYPT
+option.
+.Pp
+Note:  Because of export controls, the
+.Dv TELNET ENCRYPT
+option is not supported outside of the United States and Canada.
+.Pp
+Valid arguments for the encrypt command are as follows:
+.Bl -tag -width Ar
+.It Ic disable Ar type Ic [input|output]
+Disables the specified type of encryption.  If you
+omit the input and output, both input and output
+are disabled.  To obtain a list of available
+types, use the
+.Ic encrypt disable \&?
+command.
+.It Ic enable Ar type Ic [input|output]
+Enables the specified type of encryption.  If you
+omit input and output, both input and output are
+enabled.  To obtain a list of available types, use the
+.Ic encrypt enable \&?
+command.
+.It Ic input
+This is the same as the
+.Ic encrypt start input
+command.
+.It Ic -input
+This is the same as the
+.Ic encrypt stop input
+command.
+.It Ic output
+This is the same as the
+.Ic encrypt start output
+command.
+.It Ic -output
+This is the same as the
+.Ic encrypt stop output
+command.
+.It Ic start Ic [input|output]
+Attempts to start encryption.  If you omit
+.Ic input
+and
+.Ic output,
+both input and output are enabled.  To
+obtain a list of available types, use the
+.Ic encrypt enable \&?
+command.
+.It Ic status
+Lists the current status of encryption.
+.It Ic stop Ic [input|output]
+Stops encryption.  If you omit input and output,
+encryption is on both input and output.
+.It Ic type Ar type
+Sets the default type of encryption to be used
+with later
+.Ic encrypt start
+or
+.Ic encrypt stop
+commands.
+.El
+.It Ic environ Ar arguments... 
+The
+.Ic environ
+command is used to manipulate the
+the variables that my be sent through the
+.Dv TELNET ENVIRON
+option.
+The initial set of variables is taken from the users
+environment, with only the
+.Ev DISPLAY
+and
+.Ev PRINTER
+variables being exported by default.
+The
+.Ev USER
+variable is also exported if the
+.Fl a
+or
+.Fl l
+options are used.
+.br
+Valid arguments for the
+.Ic environ
+command are:
+.Bl -tag -width Fl
+.It Ic define Ar variable value 
+Define the variable
+.Ar variable
+to have a value of
+.Ar value.
+Any variables defined by this command are automatically exported.
+The
+.Ar value
+may be enclosed in single or double quotes so
+that tabs and spaces may be included.
+.It Ic undefine Ar variable 
+Remove
+.Ar variable
+from the list of environment variables.
+.It Ic export Ar variable 
+Mark the variable
+.Ar variable
+to be exported to the remote side.
+.It Ic unexport Ar variable 
+Mark the variable
+.Ar variable
+to not be exported unless
+explicitly asked for by the remote side.
+.It Ic list
+List the current set of environment variables.
+Those marked with a
+.Cm *
+will be sent automatically,
+other variables will only be sent if explicitly requested.
+.It Ic \&?
+Prints out help information for the
+.Ic environ
+command.
+.El
+.It Ic logout
+Sends the
+.Dv TELNET LOGOUT
+option to the remote side.
+This command is similar to a
+.Ic close
+command; however, if the remote side does not support the
+.Dv LOGOUT
+option, nothing happens.
+If, however, the remote side does support the
+.Dv LOGOUT
+option, this command should cause the remote side to close the
+.Tn TELNET
+connection.
+If the remote side also supports the concept of
+suspending a user's session for later reattachment,
+the logout argument indicates that you
+should terminate the session immediately.
+.It Ic mode Ar type 
+.Ar Type
+is one of several options, depending on the state of the
+.Tn TELNET
+session.
+The remote host is asked for permission to go into the requested mode.
+If the remote host is capable of entering that mode, the requested
+mode will be entered.
+.Bl -tag -width Ar
+.It Ic character
+Disable the
+.Dv TELNET LINEMODE
+option, or, if the remote side does not understand the
+.Dv LINEMODE
+option, then enter \*(Lqcharacter at a time\*(Lq mode.
+.It Ic line
+Enable the
+.Dv TELNET LINEMODE
+option, or, if the remote side does not understand the
+.Dv LINEMODE
+option, then attempt to enter \*(Lqold-line-by-line\*(Lq mode.
+.It Ic isig Pq Ic \-isig 
+Attempt to enable (disable) the 
+.Dv TRAPSIG
+mode of the 
+.Dv LINEMODE
+option.
+This requires that the 
+.Dv LINEMODE
+option be enabled.
+.It Ic edit Pq Ic \-edit 
+Attempt to enable (disable) the 
+.Dv EDIT
+mode of the 
+.Dv LINEMODE
+option.
+This requires that the 
+.Dv LINEMODE
+option be enabled.
+.It Ic softtabs Pq Ic \-softtabs 
+Attempt to enable (disable) the 
+.Dv SOFT_TAB
+mode of the 
+.Dv LINEMODE
+option.
+This requires that the 
+.Dv LINEMODE
+option be enabled.
+.ne 1i
+.It Ic litecho Pq Ic \-litecho 
+Attempt to enable (disable) the 
+.Dv LIT_ECHO
+mode of the 
+.Dv LINEMODE
+option.
+This requires that the 
+.Dv LINEMODE
+option be enabled.
+.It Ic \&?
+Prints out help information for the
+.Ic mode
+command.
+.El
+.It Xo
+.Ic open Ar host
+.Oo Op Fl l
+.Ar user
+.Oc Ns Oo Fl
+.Ar port Oc
+.Xc
+Open a connection to the named host.
+If no port number
+is specified,
+.Nm telnet
+will attempt to contact a
+.Tn TELNET
+server at the default port.
+The host specification may be either a host name (see
+.Xr hosts  5  )
+or an Internet address specified in the \*(Lqdot notation\*(Rq (see
+.Xr inet 3 ) .
+The
+.Op Fl l
+option may be used to specify the user name
+to be passed to the remote system via the
+.Ev ENVIRON
+option.
+When connecting to a non-standard port,
+.Nm telnet
+omits any automatic initiation of
+.Tn TELNET
+options.  When the port number is preceded by a minus sign,
+the initial option negotiation is done.
+After establishing a connection, the file
+.Pa \&.telnetrc
+in the
+users home directory is opened.  Lines beginning with a # are
+comment lines.  Blank lines are ignored.  Lines that begin
+without white space are the start of a machine entry.  The
+first thing on the line is the name of the machine that is
+being connected to.  The rest of the line, and successive
+lines that begin with white space are assumed to be
+.Nm telnet
+commands and are processed as if they had been typed
+in manually to the
+.Nm telnet
+command prompt.
+.It Ic quit
+Close any open
+.Tn TELNET
+session and exit
+.Nm telnet  .
+An end of file (in command mode) will also close a session and exit.
+.It Ic send Ar arguments 
+Sends one or more special character sequences to the remote host.
+The following are the arguments which may be specified
+(more than one argument may be specified at a time):
+.Pp
+.Bl -tag -width escape
+.It Ic abort
+Sends the
+.Dv TELNET ABORT
+(Abort
+processes)
+sequence.
+.It Ic ao
+Sends the
+.Dv TELNET AO
+(Abort Output) sequence, which should cause the remote system to flush
+all output
+.Em from
+the remote system
+.Em to
+the user's terminal.
+.It Ic ayt
+Sends the
+.Dv TELNET AYT
+(Are You There)
+sequence, to which the remote system may or may not choose to respond.
+.It Ic brk
+Sends the
+.Dv TELNET BRK
+(Break) sequence, which may have significance to the remote
+system.
+.It Ic ec
+Sends the
+.Dv TELNET EC
+(Erase Character)
+sequence, which should cause the remote system to erase the last character
+entered.
+.It Ic el
+Sends the
+.Dv TELNET EL
+(Erase Line)
+sequence, which should cause the remote system to erase the line currently
+being entered.
+.It Ic eof
+Sends the
+.Dv TELNET EOF
+(End Of File)
+sequence.
+.It Ic eor
+Sends the
+.Dv TELNET EOR
+(End of Record)
+sequence.
+.It Ic escape
+Sends the current
+.Nm telnet
+escape character (initially \*(Lq^\*(Rq).
+.It Ic ga
+Sends the
+.Dv TELNET GA
+(Go Ahead)
+sequence, which likely has no significance to the remote system.
+.It Ic getstatus
+If the remote side supports the
+.Dv TELNET STATUS
+command,
+.Ic getstatus
+will send the subnegotiation to request that the server send
+its current option status.
+.ne 1i
+.It Ic ip
+Sends the
+.Dv TELNET IP
+(Interrupt Process) sequence, which should cause the remote
+system to abort the currently running process.
+.It Ic nop
+Sends the
+.Dv TELNET NOP
+(No OPeration)
+sequence.
+.It Ic susp
+Sends the
+.Dv TELNET SUSP
+(SUSPend process)
+sequence.
+.It Ic synch
+Sends the
+.Dv TELNET SYNCH
+sequence.
+This sequence causes the remote system to discard all previously typed
+(but not yet read) input.
+This sequence is sent as
+.Tn TCP
+urgent
+data (and may not work if the remote system is a
+.Bx 4.2
+system -- if
+it doesn't work, a lower case \*(Lqr\*(Rq may be echoed on the terminal).
+.It Ic do Ar cmd
+.It Ic dont Ar cmd
+.It Ic will Ar cmd
+.It Ic wont Ar cmd
+Sends the
+.Dv TELNET DO
+.Ar cmd
+sequence.
+.Ar Cmd
+can be either a decimal number between 0 and 255,
+or a symbolic name for a specific
+.Dv TELNET
+command.
+.Ar Cmd
+can also be either
+.Ic help
+or
+.Ic \&?
+to print out help information, including
+a list of known symbolic names.
+.It Ic \&?
+Prints out help information for the
+.Ic send
+command.
+.El
+.It Ic set Ar argument value 
+.It Ic unset Ar argument value 
+The
+.Ic set
+command will set any one of a number of
+.Nm telnet
+variables to a specific value or to
+.Dv TRUE .
+The special value
+.Ic off
+turns off the function associated with
+the variable, this is equivalent to using the
+.Ic unset
+command.
+The
+.Ic unset
+command will disable or set to
+.Dv FALSE
+any of the specified functions.
+The values of variables may be interrogated with the
+.Ic display
+command.
+The variables which may be set or unset, but not toggled, are
+listed here.  In addition, any of the variables for the
+.Ic toggle
+command may be explicitly set or unset using
+the
+.Ic set
+and
+.Ic unset
+commands.
+.Bl -tag -width escape
+.It Ic ayt
+If
+.Tn TELNET
+is in localchars mode, or
+.Dv LINEMODE
+is enabled, and the status character is typed, a
+.Dv TELNET AYT
+sequence (see
+.Ic send ayt
+preceding) is sent to the
+remote host.  The initial value for the "Are You There"
+character is the terminal's status character.
+.It Ic echo
+This is the value (initially \*(Lq^E\*(Rq) which, when in
+\*(Lqline by line\*(Rq mode, toggles between doing local echoing
+of entered characters (for normal processing), and suppressing
+echoing of entered characters (for entering, say, a password).
+.It Ic eof
+If
+.Nm telnet
+is operating in
+.Dv LINEMODE
+or \*(Lqold line by line\*(Rq mode, entering this character
+as the first character on a line will cause this character to be
+sent to the remote system.
+The initial value of the eof character is taken to be the terminal's
+.Ic eof
+character.
+.It Ic erase
+If
+.Nm telnet
+is in
+.Ic localchars
+mode (see
+.Ic toggle
+.Ic localchars
+below),
+.Sy and
+if
+.Nm telnet
+is operating in \*(Lqcharacter at a time\*(Rq mode, then when this
+character is typed, a
+.Dv TELNET EC
+sequence (see
+.Ic send
+.Ic ec
+above)
+is sent to the remote system.
+The initial value for the erase character is taken to be
+the terminal's
+.Ic erase
+character.
+.It Ic escape
+This is the
+.Nm telnet
+escape character (initially \*(Lq^[\*(Rq) which causes entry
+into
+.Nm telnet
+command mode (when connected to a remote system).
+.It Ic flushoutput
+If
+.Nm telnet
+is in
+.Ic localchars
+mode (see
+.Ic toggle
+.Ic localchars
+below)
+and the
+.Ic flushoutput
+character is typed, a
+.Dv TELNET AO
+sequence (see
+.Ic send
+.Ic ao
+above)
+is sent to the remote host.
+The initial value for the flush character is taken to be
+the terminal's
+.Ic flush
+character.
+.It Ic forw1
+.It Ic forw2
+If
+.Tn TELNET
+is operating in
+.Dv LINEMODE ,
+these are the
+characters that, when typed, cause partial lines to be
+forwarded to the remote system.  The initial value for
+the forwarding characters are taken from the terminal's
+eol and eol2 characters.
+.It Ic interrupt
+If
+.Nm telnet
+is in
+.Ic localchars
+mode (see
+.Ic toggle
+.Ic localchars
+below)
+and the
+.Ic interrupt
+character is typed, a
+.Dv TELNET IP
+sequence (see
+.Ic send
+.Ic ip
+above)
+is sent to the remote host.
+The initial value for the interrupt character is taken to be
+the terminal's
+.Ic intr
+character.
+.It Ic kill
+If
+.Nm telnet
+is in
+.Ic localchars
+mode (see
+.Ic toggle
+.Ic localchars
+below),
+.Ic and
+if
+.Nm telnet
+is operating in \*(Lqcharacter at a time\*(Rq mode, then when this
+character is typed, a
+.Dv TELNET EL
+sequence (see
+.Ic send
+.Ic el
+above)
+is sent to the remote system.
+The initial value for the kill character is taken to be
+the terminal's
+.Ic kill
+character.
+.It Ic lnext
+If
+.Nm telnet
+is operating in
+.Dv LINEMODE
+or \*(Lqold line by line\*(Lq mode, then this character is taken to
+be the terminal's
+.Ic lnext
+character.
+The initial value for the lnext character is taken to be
+the terminal's
+.Ic lnext
+character.
+.It Ic quit
+If
+.Nm telnet
+is in
+.Ic localchars
+mode (see
+.Ic toggle
+.Ic localchars
+below)
+and the
+.Ic quit
+character is typed, a
+.Dv TELNET BRK
+sequence (see
+.Ic send
+.Ic brk
+above)
+is sent to the remote host.
+The initial value for the quit character is taken to be
+the terminal's
+.Ic quit
+character.
+.It Ic reprint
+If
+.Nm telnet
+is operating in
+.Dv LINEMODE
+or \*(Lqold line by line\*(Lq mode, then this character is taken to
+be the terminal's
+.Ic reprint
+character.
+The initial value for the reprint character is taken to be
+the terminal's
+.Ic reprint
+character.
+.It Ic rlogin
+This is the rlogin escape character.
+If set, the normal
+.Tn TELNET
+escape character is ignored unless it is
+preceded by this character at the beginning of a line.
+This character, at the beginning of a line followed by
+a "."  closes the connection; when followed by a ^Z it
+suspends the telnet command.  The initial state is to
+disable the rlogin escape character.
+.It Ic start
+If the
+.Dv TELNET TOGGLE-FLOW-CONTROL
+option has been enabled,
+then this character is taken to
+be the terminal's
+.Ic start
+character.
+The initial value for the kill character is taken to be
+the terminal's
+.Ic start
+character.
+.It Ic stop
+If the
+.Dv TELNET TOGGLE-FLOW-CONTROL
+option has been enabled,
+then this character is taken to
+be the terminal's
+.Ic stop
+character.
+The initial value for the kill character is taken to be
+the terminal's
+.Ic stop
+character.
+.It Ic susp
+If
+.Nm telnet
+is in
+.Ic localchars
+mode, or
+.Dv LINEMODE
+is enabled, and the
+.Ic suspend
+character is typed, a
+.Dv TELNET SUSP
+sequence (see
+.Ic send
+.Ic susp
+above)
+is sent to the remote host.
+The initial value for the suspend character is taken to be
+the terminal's
+.Ic suspend
+character.
+.ne 1i
+.It Ic tracefile
+This is the file to which the output, caused by
+.Ic netdata
+or
+.Ic option
+tracing being
+.Dv TRUE ,
+will be written.  If it is set to
+.Dq Fl ,
+then tracing information will be written to standard output (the default).
+.It Ic worderase
+If
+.Nm telnet
+is operating in
+.Dv LINEMODE
+or \*(Lqold line by line\*(Lq mode, then this character is taken to
+be the terminal's
+.Ic worderase
+character.
+The initial value for the worderase character is taken to be
+the terminal's
+.Ic worderase
+character.
+.It Ic \&?
+Displays the legal
+.Ic set
+.Pq Ic unset
+commands.
+.El
+.It Ic slc Ar state 
+The
+.Ic slc
+command (Set Local Characters) is used to set
+or change the state of the the special
+characters when the 
+.Dv TELNET LINEMODE
+option has
+been enabled.  Special characters are characters that get
+mapped to 
+.Tn TELNET
+commands sequences (like
+.Ic ip
+or
+.Ic quit  )
+or line editing characters (like
+.Ic erase
+and
+.Ic kill  ) .
+By default, the local special characters are exported.
+.Bl -tag -width Fl
+.It Ic check
+Verify the current settings for the current special characters.
+The remote side is requested to send all the current special
+character settings, and if there are any discrepancies with
+the local side, the local side will switch to the remote value.
+.It Ic export
+Switch to the local defaults for the special characters.  The
+local default characters are those of the local terminal at
+the time when
+.Nm telnet
+was started.
+.It Ic import
+Switch to the remote defaults for the special characters.
+The remote default characters are those of the remote system
+at the time when the 
+.Tn TELNET
+connection was established.
+.It Ic \&?
+Prints out help information for the
+.Ic slc
+command.
+.El
+.It Ic status
+Show the current status of
+.Nm telnet  .
+This includes the peer one is connected to, as well
+as the current mode.
+.It Ic toggle Ar arguments ... 
+Toggle (between
+.Dv TRUE
+and
+.Dv FALSE )
+various flags that control how
+.Nm telnet
+responds to events.
+These flags may be set explicitly to
+.Dv TRUE
+or
+.Dv FALSE
+using the
+.Ic set
+and
+.Ic unset
+commands listed above.
+More than one argument may be specified.
+The state of these flags may be interrogated with the
+.Ic display
+command.
+Valid arguments are:
+.Bl -tag -width Ar
+.It Ic authdebug
+Turns on debugging information for the authentication code.
+.It Ic autoflush
+If
+.Ic autoflush
+and
+.Ic localchars
+are both
+.Dv TRUE ,
+then when the
+.Ic ao  ,
+or
+.Ic quit
+characters are recognized (and transformed into
+.Tn TELNET
+sequences; see
+.Ic set
+above for details),
+.Nm telnet
+refuses to display any data on the user's terminal
+until the remote system acknowledges (via a
+.Dv TELNET TIMING MARK
+option)
+that it has processed those
+.Tn TELNET
+sequences.
+The initial value for this toggle is
+.Dv TRUE
+if the terminal user had not
+done an "stty noflsh", otherwise
+.Dv FALSE
+(see
+.Xr stty  1  ) .
+.It Ic autodecrypt
+When the
+.Dv TELNET ENCRYPT
+option is negotiated, by
+default the actual encryption (decryption) of the data
+stream does not start automatically.  The autoencrypt
+(autodecrypt) command states that encryption of the
+output (input) stream should be enabled as soon as
+possible.
+.sp
+.Pp
+Note:  Because of export controls, the
+.Dv TELNET ENCRYPT
+option is not supported outside the United States and Canada.
+.It Ic autologin
+If the remote side supports the
+.Dv TELNET AUTHENTICATION
+option
+.Tn TELNET
+attempts to use it to perform automatic authentication.  If the
+.Dv AUTHENTICATION
+option is not supported, the user's login
+name are propagated through the
+.Dv TELNET ENVIRON
+option.
+This command is the same as specifying
+.Ar a
+option on the
+.Ic open
+command.
+.It Ic autosynch
+If
+.Ic autosynch
+and
+.Ic localchars
+are both
+.Dv TRUE ,
+then when either the
+.Ic intr
+or
+.Ic quit
+characters is typed (see
+.Ic set
+above for descriptions of the
+.Ic intr
+and
+.Ic quit
+characters), the resulting
+.Tn TELNET
+sequence sent is followed by the
+.Dv TELNET SYNCH
+sequence.
+This procedure
+.Ic should
+cause the remote system to begin throwing away all previously
+typed input until both of the
+.Tn TELNET
+sequences have been read and acted upon.
+The initial value of this toggle is
+.Dv FALSE .
+.It Ic binary
+Enable or disable the
+.Dv TELNET BINARY
+option on both input and output.
+.It Ic inbinary
+Enable or disable the
+.Dv TELNET BINARY
+option on input.
+.It Ic outbinary
+Enable or disable the
+.Dv TELNET BINARY
+option on output.
+.It Ic crlf
+If this is
+.Dv TRUE ,
+then carriage returns will be sent as
+.Li <CR><LF> .
+If this is
+.Dv FALSE ,
+then carriage returns will be send as
+.Li <CR><NUL> .
+The initial value for this toggle is
+.Dv FALSE .
+.It Ic crmod
+Toggle carriage return mode.
+When this mode is enabled, most carriage return characters received from
+the remote host will be mapped into a carriage return followed by
+a line feed.
+This mode does not affect those characters typed by the user, only
+those received from the remote host.
+This mode is not very useful unless the remote host
+only sends carriage return, but never line feed.
+The initial value for this toggle is
+.Dv FALSE .
+.It Ic debug
+Toggles socket level debugging (useful only to the
+.Ic super user  ) .
+The initial value for this toggle is
+.Dv FALSE .
+.It Ic encdebug
+Turns on debugging information for the encryption code.
+.It Ic localchars
+If this is
+.Dv TRUE ,
+then the
+.Ic flush  ,
+.Ic interrupt ,
+.Ic quit  ,
+.Ic erase ,
+and
+.Ic kill
+characters (see
+.Ic set
+above) are recognized locally, and transformed into (hopefully) appropriate
+.Tn TELNET
+control sequences
+(respectively
+.Ic ao  ,
+.Ic ip ,
+.Ic brk  ,
+.Ic ec ,
+and
+.Ic el  ;
+see
+.Ic send
+above).
+The initial value for this toggle is
+.Dv TRUE
+in \*(Lqold line by line\*(Rq mode,
+and
+.Dv FALSE
+in \*(Lqcharacter at a time\*(Rq mode.
+When the
+.Dv LINEMODE
+option is enabled, the value of
+.Ic localchars
+is ignored, and assumed to always be
+.Dv TRUE .
+If
+.Dv LINEMODE
+has ever been enabled, then
+.Ic quit
+is sent as
+.Ic abort  ,
+and
+.Ic eof and
+.B suspend
+are sent as
+.Ic eof and
+.Ic susp ,
+see
+.Ic send
+above).
+.It Ic netdata
+Toggles the display of all network data (in hexadecimal format).
+The initial value for this toggle is
+.Dv FALSE .
+.It Ic options
+Toggles the display of some internal
+.Nm telnet
+protocol processing (having to do with
+.Tn TELNET
+options).
+The initial value for this toggle is
+.Dv FALSE .
+.ne 1i
+.It Ic prettydump
+When the
+.Ic netdata
+toggle is enabled, if
+.Ic prettydump
+is enabled the output from the
+.Ic netdata
+command will be formatted in a more user readable format.
+Spaces are put between each character in the output, and the
+beginning of any
+.Tn TELNET
+escape sequence is preceded by a '*' to aid in locating them.
+.It Ic skiprc
+When the skiprc toggle is
+.Dv TRUE ,
+.Tn TELNET
+skips the reading of the
+.Pa \&.telnetrc
+file in the users home
+directory when connections are opened.  The initial
+value for this toggle is
+.Dv FALSE.
+.It Ic termdata
+Toggles the display of all terminal data (in hexadecimal format).
+The initial value for this toggle is
+.Dv FALSE .
+.It Ic verbose_encrypt
+When the
+.Ic verbose_encrypt
+toggle is
+.Dv TRUE ,
+.Tn TELNET
+prints out a message each time encryption is enabled or
+disabled.  The initial value for this toggle is
+.Dv FALSE.
+Note:  Because of export controls, data encryption
+is not supported outside of the United States and Canada.
+.It Ic \&?
+Displays the legal
+.Ic toggle
+commands.
+.El
+.It Ic z
+Suspend
+.Nm telnet  .
+This command only works when the user is using the
+.Xr csh  1  .
+.It Ic \&! Op Ar command 
+Execute a single command in a subshell on the local
+system.  If
+.Ic command
+is omitted, then an interactive
+subshell is invoked.
+.It Ic \&? Op Ar command 
+Get help.  With no arguments,
+.Nm telnet
+prints a help summary.
+If a command is specified,
+.Nm telnet
+will print the help information for just that command.
+.El
+.Sh ENVIRONMENT
+.Nm Telnet
+uses at least the
+.Ev HOME ,
+.Ev SHELL ,
+.Ev DISPLAY ,
+and
+.Ev TERM
+environment variables.
+Other environment variables may be propagated
+to the other side via the
+.Dv TELNET ENVIRON
+option.
+.Sh FILES
+.Bl -tag -width ~/.telnetrc -compact
+.It Pa ~/.telnetrc
+user customized telnet startup values
+.El
+.Sh HISTORY
+The
+.Nm Telnet
+command appeared in
+.Bx 4.2 .
+.Sh NOTES
+.Pp
+On some remote systems, echo has to be turned off manually when in
+\*(Lqold line by line\*(Rq mode.
+.Pp
+In \*(Lqold line by line\*(Rq mode or 
+.Dv LINEMODE
+the terminal's
+.Ic eof
+character is only recognized (and sent to the remote system)
+when it is the first character on a line.
diff --git a/telnet.tproj/telnet.c b/telnet.tproj/telnet.c
new file mode 100644 (file)
index 0000000..e1a974f
--- /dev/null
@@ -0,0 +1,2673 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)telnet.c   8.4 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#if    defined(unix) || defined(__APPLE__)
+#include <signal.h>
+/* By the way, we need to include curses.h before telnet.h since,
+ * among other things, telnet.h #defines 'DO', which is a variable
+ * declared in curses.h.
+ */
+#endif /* defined(unix) || defined(__APPLE__) */
+
+#include <arpa/telnet.h>
+
+#include <ctype.h>
+
+#include "ring.h"
+
+#include "defines.h"
+#include "externs.h"
+#include "types.h"
+#include "general.h"
+
+\f
+#define        strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
+
+static unsigned char   subbuffer[SUBBUFSIZE],
+                       *subpointer, *subend;    /* buffer for sub-options */
+#define        SB_CLEAR()      subpointer = subbuffer;
+#define        SB_TERM()       { subend = subpointer; SB_CLEAR(); }
+#define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
+                               *subpointer++ = (c); \
+                       }
+
+#define        SB_GET()        ((*subpointer++)&0xff)
+#define        SB_PEEK()       ((*subpointer)&0xff)
+#define        SB_EOF()        (subpointer >= subend)
+#define        SB_LEN()        (subend - subpointer)
+
+char   options[256];           /* The combined options */
+char   do_dont_resp[256];
+char   will_wont_resp[256];
+
+int
+       eight = 0,
+       autologin = 0,  /* Autologin anyone? */
+       skiprc = 0,
+       connected,
+       showoptions,
+       In3270,         /* Are we in 3270 mode? */
+       ISend,          /* trying to send network data in */
+       debug = 0,
+       crmod,
+       netdata,        /* Print out network data flow */
+       crlf,           /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
+#if    defined(TN3270)
+       noasynchtty = 0,/* User specified "-noasynch" on command line */
+       noasynchnet = 0,/* User specified "-noasynch" on command line */
+       askedSGA = 0,   /* We have talked about suppress go ahead */
+#endif /* defined(TN3270) */
+       telnetport,
+       SYNCHing,       /* we are in TELNET SYNCH mode */
+       flushout,       /* flush output */
+       autoflush = 0,  /* flush output when interrupting? */
+       autosynch,      /* send interrupt characters with SYNCH? */
+       localflow,      /* we handle flow control locally */
+       restartany,     /* if flow control enabled, restart on any character */
+       localchars,     /* we recognize interrupt/quit */
+       donelclchars,   /* the user has set "localchars" */
+       donebinarytoggle,       /* the user has put us in binary */
+       dontlecho,      /* do we suppress local echoing right now? */
+       globalmode;
+
+char *prompt = 0;
+
+cc_t escape;
+cc_t rlogin;
+#ifdef KLUDGELINEMODE
+cc_t echoc;
+#endif
+
+/*
+ * Telnet receiver states for fsm
+ */
+#define        TS_DATA         0
+#define        TS_IAC          1
+#define        TS_WILL         2
+#define        TS_WONT         3
+#define        TS_DO           4
+#define        TS_DONT         5
+#define        TS_CR           6
+#define        TS_SB           7               /* sub-option collection */
+#define        TS_SE           8               /* looking for sub-option end */
+
+static int     telrcv_state;
+#ifdef OLD_ENVIRON
+unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
+#else
+# define telopt_environ TELOPT_NEW_ENVIRON
+#endif
+
+jmp_buf        toplevel = { 0 };
+jmp_buf        peerdied;
+
+int    flushline;
+int    linemode;
+
+#ifdef KLUDGELINEMODE
+int    kludgelinemode = 1;
+#endif
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+Clocks clocks;
+\f
+#ifdef notdef
+Modelist modelist[] = {
+       { "telnet command mode", COMMAND_LINE },
+       { "character-at-a-time mode", 0 },
+       { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
+       { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
+       { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
+       { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
+       { "3270 mode", 0 },
+};
+#endif
+
+\f
+/*
+ * Initialize telnet environment.
+ */
+
+    void
+init_telnet()
+{
+    env_init();
+
+    SB_CLEAR();
+    ClearArray(options);
+
+    connected = In3270 = ISend = localflow = donebinarytoggle = 0;
+#if    defined(AUTHENTICATION) || defined(ENCRYPTION)
+    auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION)  */
+    restartany = -1;
+
+    SYNCHing = 0;
+
+    /* Don't change NetTrace */
+
+    escape = CONTROL(']');
+    rlogin = _POSIX_VDISABLE;
+#ifdef KLUDGELINEMODE
+    echoc = CONTROL('E');
+#endif
+
+    flushline = 1;
+    telrcv_state = TS_DATA;
+}
+\f
+
+#ifdef notdef
+#include <varargs.h>
+
+    /*VARARGS*/
+    static void
+printring(va_alist)
+    va_dcl
+{
+    va_list ap;
+    char buffer[100];          /* where things go */
+    char *ptr;
+    char *format;
+    char *string;
+    Ring *ring;
+    int i;
+
+    va_start(ap);
+
+    ring = va_arg(ap, Ring *);
+    format = va_arg(ap, char *);
+    ptr = buffer;
+
+    while ((i = *format++) != 0) {
+       if (i == '%') {
+           i = *format++;
+           switch (i) {
+           case 'c':
+               *ptr++ = va_arg(ap, int);
+               break;
+           case 's':
+               string = va_arg(ap, char *);
+               ring_supply_data(ring, buffer, ptr-buffer);
+               ring_supply_data(ring, string, strlen(string));
+               ptr = buffer;
+               break;
+           case 0:
+               ExitString("printring: trailing %%.\n", 1);
+               /*NOTREACHED*/
+           default:
+               ExitString("printring: unknown format character.\n", 1);
+               /*NOTREACHED*/
+           }
+       } else {
+           *ptr++ = i;
+       }
+    }
+    ring_supply_data(ring, buffer, ptr-buffer);
+}
+#endif
+
+/*
+ * These routines are in charge of sending option negotiations
+ * to the other side.
+ *
+ * The basic idea is that we send the negotiation if either side
+ * is in disagreement as to what the current state should be.
+ */
+
+    void
+send_do(c, init)
+    register int c, init;
+{
+    if (init) {
+       if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
+                               my_want_state_is_do(c))
+           return;
+       set_my_want_state_do(c);
+       do_dont_resp[c]++;
+    }
+    NET2ADD(IAC, DO);
+    NETADD(c);
+    printoption("SENT", DO, c);
+}
+
+    void
+send_dont(c, init)
+    register int c, init;
+{
+    if (init) {
+       if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
+                               my_want_state_is_dont(c))
+           return;
+       set_my_want_state_dont(c);
+       do_dont_resp[c]++;
+    }
+    NET2ADD(IAC, DONT);
+    NETADD(c);
+    printoption("SENT", DONT, c);
+}
+
+    void
+send_will(c, init)
+    register int c, init;
+{
+    if (init) {
+       if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
+                               my_want_state_is_will(c))
+           return;
+       set_my_want_state_will(c);
+       will_wont_resp[c]++;
+    }
+    NET2ADD(IAC, WILL);
+    NETADD(c);
+    printoption("SENT", WILL, c);
+}
+
+    void
+send_wont(c, init)
+    register int c, init;
+{
+    if (init) {
+       if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
+                               my_want_state_is_wont(c))
+           return;
+       set_my_want_state_wont(c);
+       will_wont_resp[c]++;
+    }
+    NET2ADD(IAC, WONT);
+    NETADD(c);
+    printoption("SENT", WONT, c);
+}
+
+
+       void
+willoption(option)
+       int option;
+{
+       int new_state_ok = 0;
+
+       if (do_dont_resp[option]) {
+           --do_dont_resp[option];
+           if (do_dont_resp[option] && my_state_is_do(option))
+               --do_dont_resp[option];
+       }
+
+       if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
+
+           switch (option) {
+
+           case TELOPT_ECHO:
+#          if defined(TN3270)
+               /*
+                * The following is a pain in the rear-end.
+                * Various IBM servers (some versions of Wiscnet,
+                * possibly Fibronics/Spartacus, and who knows who
+                * else) will NOT allow us to send "DO SGA" too early
+                * in the setup proceedings.  On the other hand,
+                * 4.2 servers (telnetd) won't set SGA correctly.
+                * So, we are stuck.  Empirically (but, based on
+                * a VERY small sample), the IBM servers don't send
+                * out anything about ECHO, so we postpone our sending
+                * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
+                * DO send).
+                 */
+               {
+                   if (askedSGA == 0) {
+                       askedSGA = 1;
+                       if (my_want_state_is_dont(TELOPT_SGA))
+                           send_do(TELOPT_SGA, 1);
+                   }
+               }
+                   /* Fall through */
+           case TELOPT_EOR:
+#endif     /* defined(TN3270) */
+           case TELOPT_BINARY:
+           case TELOPT_SGA:
+               settimer(modenegotiated);
+               /* FALL THROUGH */
+           case TELOPT_STATUS:
+#if    defined(AUTHENTICATION)
+           case TELOPT_AUTHENTICATION:
+#endif
+#ifdef ENCRYPTION
+           case TELOPT_ENCRYPT:
+#endif /* ENCRYPTION */
+               new_state_ok = 1;
+               break;
+
+           case TELOPT_TM:
+               if (flushout)
+                   flushout = 0;
+               /*
+                * Special case for TM.  If we get back a WILL,
+                * pretend we got back a WONT.
+                */
+               set_my_want_state_dont(option);
+               set_my_state_dont(option);
+               return;                 /* Never reply to TM will's/wont's */
+
+           case TELOPT_LINEMODE:
+           default:
+               break;
+           }
+
+           if (new_state_ok) {
+               set_my_want_state_do(option);
+               send_do(option, 0);
+               setconnmode(0);         /* possibly set new tty mode */
+           } else {
+               do_dont_resp[option]++;
+               send_dont(option, 0);
+           }
+       }
+       set_my_state_do(option);
+#ifdef ENCRYPTION
+       if (option == TELOPT_ENCRYPT)
+               encrypt_send_support();
+#endif /* ENCRYPTION */
+}
+
+       void
+wontoption(option)
+       int option;
+{
+       if (do_dont_resp[option]) {
+           --do_dont_resp[option];
+           if (do_dont_resp[option] && my_state_is_dont(option))
+               --do_dont_resp[option];
+       }
+
+       if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
+
+           switch (option) {
+
+#ifdef KLUDGELINEMODE
+           case TELOPT_SGA:
+               if (!kludgelinemode)
+                   break;
+               /* FALL THROUGH */
+#endif
+           case TELOPT_ECHO:
+               settimer(modenegotiated);
+               break;
+
+           case TELOPT_TM:
+               if (flushout)
+                   flushout = 0;
+               set_my_want_state_dont(option);
+               set_my_state_dont(option);
+               return;         /* Never reply to TM will's/wont's */
+
+           default:
+               break;
+           }
+           set_my_want_state_dont(option);
+           if (my_state_is_do(option))
+               send_dont(option, 0);
+           setconnmode(0);                     /* Set new tty mode */
+       } else if (option == TELOPT_TM) {
+           /*
+            * Special case for TM.
+            */
+           if (flushout)
+               flushout = 0;
+           set_my_want_state_dont(option);
+       }
+       set_my_state_dont(option);
+}
+
+       static void
+dooption(option)
+       int option;
+{
+       int new_state_ok = 0;
+
+       if (will_wont_resp[option]) {
+           --will_wont_resp[option];
+           if (will_wont_resp[option] && my_state_is_will(option))
+               --will_wont_resp[option];
+       }
+
+       if (will_wont_resp[option] == 0) {
+         if (my_want_state_is_wont(option)) {
+
+           switch (option) {
+
+           case TELOPT_TM:
+               /*
+                * Special case for TM.  We send a WILL, but pretend
+                * we sent WONT.
+                */
+               send_will(option, 0);
+               set_my_want_state_wont(TELOPT_TM);
+               set_my_state_wont(TELOPT_TM);
+               return;
+
+#      if defined(TN3270)
+           case TELOPT_EOR:            /* end of record */
+#      endif   /* defined(TN3270) */
+           case TELOPT_BINARY:         /* binary mode */
+           case TELOPT_NAWS:           /* window size */
+           case TELOPT_TSPEED:         /* terminal speed */
+           case TELOPT_LFLOW:          /* local flow control */
+           case TELOPT_TTYPE:          /* terminal type option */
+           case TELOPT_SGA:            /* no big deal */
+#ifdef ENCRYPTION
+           case TELOPT_ENCRYPT:        /* encryption variable option */
+#endif /* ENCRYPTION */
+               new_state_ok = 1;
+               break;
+
+           case TELOPT_NEW_ENVIRON:    /* New environment variable option */
+#ifdef OLD_ENVIRON
+               if (my_state_is_will(TELOPT_OLD_ENVIRON))
+                       send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
+               goto env_common;
+           case TELOPT_OLD_ENVIRON:    /* Old environment variable option */
+               if (my_state_is_will(TELOPT_NEW_ENVIRON))
+                       break;          /* Don't enable if new one is in use! */
+           env_common:
+               telopt_environ = option;
+#endif
+               new_state_ok = 1;
+               break;
+
+#if    defined(AUTHENTICATION)
+           case TELOPT_AUTHENTICATION:
+               if (autologin)
+                       new_state_ok = 1;
+               break;
+#endif
+
+           case TELOPT_XDISPLOC:       /* X Display location */
+               if (env_getvalue((unsigned char *)"DISPLAY"))
+                   new_state_ok = 1;
+               break;
+
+           case TELOPT_LINEMODE:
+#ifdef KLUDGELINEMODE
+               kludgelinemode = 0;
+               send_do(TELOPT_SGA, 1);
+#endif
+               set_my_want_state_will(TELOPT_LINEMODE);
+               send_will(option, 0);
+               set_my_state_will(TELOPT_LINEMODE);
+               slc_init();
+               return;
+
+           case TELOPT_ECHO:           /* We're never going to echo... */
+           default:
+               break;
+           }
+
+           if (new_state_ok) {
+               set_my_want_state_will(option);
+               send_will(option, 0);
+               setconnmode(0);                 /* Set new tty mode */
+           } else {
+               will_wont_resp[option]++;
+               send_wont(option, 0);
+           }
+         } else {
+           /*
+            * Handle options that need more things done after the
+            * other side has acknowledged the option.
+            */
+           switch (option) {
+           case TELOPT_LINEMODE:
+#ifdef KLUDGELINEMODE
+               kludgelinemode = 0;
+               send_do(TELOPT_SGA, 1);
+#endif
+               set_my_state_will(option);
+               slc_init();
+               send_do(TELOPT_SGA, 0);
+               return;
+           }
+         }
+       }
+       set_my_state_will(option);
+}
+
+       static void
+dontoption(option)
+       int option;
+{
+
+       if (will_wont_resp[option]) {
+           --will_wont_resp[option];
+           if (will_wont_resp[option] && my_state_is_wont(option))
+               --will_wont_resp[option];
+       }
+
+       if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
+           switch (option) {
+           case TELOPT_LINEMODE:
+               linemode = 0;   /* put us back to the default state */
+               break;
+#ifdef OLD_ENVIRON
+           case TELOPT_NEW_ENVIRON:
+               /*
+                * The new environ option wasn't recognized, try
+                * the old one.
+                */
+               send_will(TELOPT_OLD_ENVIRON, 1);
+               telopt_environ = TELOPT_OLD_ENVIRON;
+               break;
+#endif
+           }
+           /* we always accept a DONT */
+           set_my_want_state_wont(option);
+           if (my_state_is_will(option))
+               send_wont(option, 0);
+           setconnmode(0);                     /* Set new tty mode */
+       }
+       set_my_state_wont(option);
+}
+
+/*
+ * Given a buffer returned by tgetent(), this routine will turn
+ * the pipe seperated list of names in the buffer into an array
+ * of pointers to null terminated names.  We toss out any bad,
+ * duplicate, or verbose names (names with spaces).
+ */
+
+static char *name_unknown = "UNKNOWN";
+static char *unknown[] = { 0, 0 };
+
+       char **
+mklist(buf, name)
+       char *buf, *name;
+{
+       register int n;
+       register char c, *cp, **argvp, *cp2, **argv, **avt;
+
+       if (name) {
+               if ((int)strlen(name) > 40) {
+                       name = 0;
+                       unknown[0] = name_unknown;
+               } else {
+                       unknown[0] = name;
+                       upcase(name);
+               }
+       } else
+               unknown[0] = name_unknown;
+       /*
+        * Count up the number of names.
+        */
+       for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
+               if (*cp == '|')
+                       n++;
+       }
+       /*
+        * Allocate an array to put the name pointers into
+        */
+       argv = (char **)malloc((n+3)*sizeof(char *));
+       if (argv == 0)
+               return(unknown);
+
+       /*
+        * Fill up the array of pointers to names.
+        */
+       *argv = 0;
+       argvp = argv+1;
+       n = 0;
+       for (cp = cp2 = buf; (c = *cp);  cp++) {
+               if (c == '|' || c == ':') {
+                       *cp++ = '\0';
+                       /*
+                        * Skip entries that have spaces or are over 40
+                        * characters long.  If this is our environment
+                        * name, then put it up front.  Otherwise, as
+                        * long as this is not a duplicate name (case
+                        * insensitive) add it to the list.
+                        */
+                       if (n || (cp - cp2 > 41))
+                               ;
+                       else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
+                               *argv = cp2;
+                       else if (is_unique(cp2, argv+1, argvp))
+                               *argvp++ = cp2;
+                       if (c == ':')
+                               break;
+                       /*
+                        * Skip multiple delimiters. Reset cp2 to
+                        * the beginning of the next name. Reset n,
+                        * the flag for names with spaces.
+                        */
+                       while ((c = *cp) == '|')
+                               cp++;
+                       cp2 = cp;
+                       n = 0;
+               }
+               /*
+                * Skip entries with spaces or non-ascii values.
+                * Convert lower case letters to upper case.
+                */
+               if ((c == ' ') || !isascii(c))
+                       n = 1;
+               else if (islower(c))
+                       *cp = toupper(c);
+       }
+
+       /*
+        * Check for an old V6 2 character name.  If the second
+        * name points to the beginning of the buffer, and is
+        * only 2 characters long, move it to the end of the array.
+        */
+       if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
+               --argvp;
+               for (avt = &argv[1]; avt < argvp; avt++)
+                       *avt = *(avt+1);
+               *argvp++ = buf;
+       }
+
+       /*
+        * Duplicate last name, for TTYPE option, and null
+        * terminate the array.  If we didn't find a match on
+        * our terminal name, put that name at the beginning.
+        */
+       cp = *(argvp-1);
+       *argvp++ = cp;
+       *argvp = 0;
+
+       if (*argv == 0) {
+               if (name)
+                       *argv = name;
+               else {
+                       --argvp;
+                       for (avt = argv; avt < argvp; avt++)
+                               *avt = *(avt+1);
+               }
+       }
+       if (*argv)
+               return(argv);
+       else
+               return(unknown);
+}
+
+       int
+is_unique(name, as, ae)
+       register char *name, **as, **ae;
+{
+       register char **ap;
+       register int n;
+
+       n = strlen(name) + 1;
+       for (ap = as; ap < ae; ap++)
+               if (strncasecmp(*ap, name, n) == 0)
+                       return(0);
+       return (1);
+}
+
+#ifdef TERMCAP
+char termbuf[1024];
+
+       /*ARGSUSED*/
+       int
+setupterm(tname, fd, errp)
+       char *tname;
+       int fd, *errp;
+{
+       if (tgetent(termbuf, tname) == 1) {
+               termbuf[1023] = '\0';
+               if (errp)
+                       *errp = 1;
+               return(0);
+       }
+       if (errp)
+               *errp = 0;
+       return(-1);
+}
+#else
+#define        termbuf ttytype
+extern char ttytype[];
+#endif
+
+int resettermname = 1;
+
+       char *
+gettermname()
+{
+       char *tname;
+       static char **tnamep = 0;
+       static char **next;
+       int err;
+
+       if (resettermname) {
+               resettermname = 0;
+               if (tnamep && tnamep != unknown)
+                       free(tnamep);
+               if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
+                               (setupterm(tname, 1, &err) == 0)) {
+                       tnamep = mklist(termbuf, tname);
+               } else {
+                       if (tname && ((int)strlen(tname) <= 40)) {
+                               unknown[0] = tname;
+                               upcase(tname);
+                       } else
+                               unknown[0] = name_unknown;
+                       tnamep = unknown;
+               }
+               next = tnamep;
+       }
+       if (*next == 0)
+               next = tnamep;
+       return(*next++);
+}
+/*
+ * suboption()
+ *
+ *     Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ *
+ *     Currently we recognize:
+ *
+ *             Terminal type, send request.
+ *             Terminal speed (send request).
+ *             Local flow control (is request).
+ *             Linemode
+ */
+
+    static void
+suboption()
+{
+    unsigned char subchar;
+
+    printsub('<', subbuffer, SB_LEN()+2);
+    switch (subchar = SB_GET()) {
+    case TELOPT_TTYPE:
+       if (my_want_state_is_wont(TELOPT_TTYPE))
+           return;
+       if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
+           return;
+       } else {
+           char *name;
+           unsigned char temp[50];
+           int len;
+
+#if    defined(TN3270)
+           if (tn3270_ttype()) {
+               return;
+           }
+#endif /* defined(TN3270) */
+           name = gettermname();
+           len = strlen(name) + 4 + 2;
+           if (len < NETROOM()) {
+               sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
+                               TELQUAL_IS, name, IAC, SE);
+               ring_supply_data(&netoring, temp, len);
+               printsub('>', &temp[2], len-2);
+           } else {
+               ExitString("No room in buffer for terminal type.\n", 1);
+               /*NOTREACHED*/
+           }
+       }
+       break;
+    case TELOPT_TSPEED:
+       if (my_want_state_is_wont(TELOPT_TSPEED))
+           return;
+       if (SB_EOF())
+           return;
+       if (SB_GET() == TELQUAL_SEND) {
+           long ospeed, ispeed;
+           unsigned char temp[50];
+           int len;
+
+           TerminalSpeeds(&ispeed, &ospeed);
+
+           sprintf((char *)temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED,
+                   TELQUAL_IS, ospeed, ispeed, IAC, SE);
+           len = strlen((char *)temp+4) + 4;   /* temp[3] is 0 ... */
+
+           if (len < NETROOM()) {
+               ring_supply_data(&netoring, temp, len);
+               printsub('>', temp+2, len - 2);
+           }
+/*@*/      else printf("lm_will: not enough room in buffer\n");
+       }
+       break;
+    case TELOPT_LFLOW:
+       if (my_want_state_is_wont(TELOPT_LFLOW))
+           return;
+       if (SB_EOF())
+           return;
+       switch(SB_GET()) {
+       case LFLOW_RESTART_ANY:
+           restartany = 1;
+           break;
+       case LFLOW_RESTART_XON:
+           restartany = 0;
+           break;
+       case LFLOW_ON:
+           localflow = 1;
+           break;
+       case LFLOW_OFF:
+           localflow = 0;
+           break;
+       default:
+           return;
+       }
+       setcommandmode();
+       setconnmode(0);
+       break;
+
+    case TELOPT_LINEMODE:
+       if (my_want_state_is_wont(TELOPT_LINEMODE))
+           return;
+       if (SB_EOF())
+           return;
+       switch (SB_GET()) {
+       case WILL:
+           lm_will(subpointer, SB_LEN());
+           break;
+       case WONT:
+           lm_wont(subpointer, SB_LEN());
+           break;
+       case DO:
+           lm_do(subpointer, SB_LEN());
+           break;
+       case DONT:
+           lm_dont(subpointer, SB_LEN());
+           break;
+       case LM_SLC:
+           slc(subpointer, SB_LEN());
+           break;
+       case LM_MODE:
+           lm_mode(subpointer, SB_LEN(), 0);
+           break;
+       default:
+           break;
+       }
+       break;
+
+#ifdef OLD_ENVIRON
+    case TELOPT_OLD_ENVIRON:
+#endif
+    case TELOPT_NEW_ENVIRON:
+       if (SB_EOF())
+           return;
+       switch(SB_PEEK()) {
+       case TELQUAL_IS:
+       case TELQUAL_INFO:
+           if (my_want_state_is_dont(subchar))
+               return;
+           break;
+       case TELQUAL_SEND:
+           if (my_want_state_is_wont(subchar)) {
+               return;
+           }
+           break;
+       default:
+           return;
+       }
+       env_opt(subpointer, SB_LEN());
+       break;
+
+    case TELOPT_XDISPLOC:
+       if (my_want_state_is_wont(TELOPT_XDISPLOC))
+           return;
+       if (SB_EOF())
+           return;
+       if (SB_GET() == TELQUAL_SEND) {
+           unsigned char temp[50], *dp;
+           int len;
+
+           if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
+               /*
+                * Something happened, we no longer have a DISPLAY
+                * variable.  So, turn off the option.
+                */
+               send_wont(TELOPT_XDISPLOC, 1);
+               break;
+           }
+           sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
+                   TELQUAL_IS, dp, IAC, SE);
+           len = strlen((char *)temp+4) + 4;   /* temp[3] is 0 ... */
+
+           if (len < NETROOM()) {
+               ring_supply_data(&netoring, temp, len);
+               printsub('>', temp+2, len - 2);
+           }
+/*@*/      else printf("lm_will: not enough room in buffer\n");
+       }
+       break;
+
+#if    defined(AUTHENTICATION)
+       case TELOPT_AUTHENTICATION: {
+               if (!autologin)
+                       break;
+               if (SB_EOF())
+                       return;
+               switch(SB_GET()) {
+               case TELQUAL_IS:
+                       if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_is(subpointer, SB_LEN());
+                       break;
+               case TELQUAL_SEND:
+                       if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_send(subpointer, SB_LEN());
+                       break;
+               case TELQUAL_REPLY:
+                       if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_reply(subpointer, SB_LEN());
+                       break;
+               case TELQUAL_NAME:
+                       if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+                               return;
+                       auth_name(subpointer, SB_LEN());
+                       break;
+               }
+       }
+       break;
+#endif
+#ifdef ENCRYPTION
+       case TELOPT_ENCRYPT:
+               if (SB_EOF())
+                       return;
+               switch(SB_GET()) {
+               case ENCRYPT_START:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_start(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_END:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_end();
+                       break;
+               case ENCRYPT_SUPPORT:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_support(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_REQSTART:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_request_start(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_REQEND:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       /*
+                        * We can always send an REQEND so that we cannot
+                        * get stuck encrypting.  We should only get this
+                        * if we have been able to get in the correct mode
+                        * anyhow.
+                        */
+                       encrypt_request_end();
+                       break;
+               case ENCRYPT_IS:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_is(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_REPLY:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_reply(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_ENC_KEYID:
+                       if (my_want_state_is_dont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_enc_keyid(subpointer, SB_LEN());
+                       break;
+               case ENCRYPT_DEC_KEYID:
+                       if (my_want_state_is_wont(TELOPT_ENCRYPT))
+                               return;
+                       encrypt_dec_keyid(subpointer, SB_LEN());
+                       break;
+               default:
+                       break;
+               }
+               break;
+#endif /* ENCRYPTION */
+    default:
+       break;
+    }
+}
+
+static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
+
+    void
+lm_will(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/  printf("lm_will: no command!!!\n");     /* Should not happen... */
+       return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:       /* We shouldn't ever get this... */
+    default:
+       str_lm[3] = DONT;
+       str_lm[4] = cmd[0];
+       if (NETROOM() > sizeof(str_lm)) {
+           ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+           printsub('>', &str_lm[2], sizeof(str_lm)-2);
+       }
+/*@*/  else printf("lm_will: not enough room in buffer\n");
+       break;
+    }
+}
+
+    void
+lm_wont(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/  printf("lm_wont: no command!!!\n");     /* Should not happen... */
+       return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:       /* We shouldn't ever get this... */
+    default:
+       /* We are always DONT, so don't respond */
+       return;
+    }
+}
+
+    void
+lm_do(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/  printf("lm_do: no command!!!\n");       /* Should not happen... */
+       return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:
+    default:
+       str_lm[3] = WONT;
+       str_lm[4] = cmd[0];
+       if (NETROOM() > sizeof(str_lm)) {
+           ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+           printsub('>', &str_lm[2], sizeof(str_lm)-2);
+       }
+/*@*/  else printf("lm_do: not enough room in buffer\n");
+       break;
+    }
+}
+
+    void
+lm_dont(cmd, len)
+    unsigned char *cmd;
+    int len;
+{
+    if (len < 1) {
+/*@*/  printf("lm_dont: no command!!!\n");     /* Should not happen... */
+       return;
+    }
+    switch(cmd[0]) {
+    case LM_FORWARDMASK:
+    default:
+       /* we are always WONT, so don't respond */
+       break;
+    }
+}
+
+static unsigned char str_lm_mode[] = {
+       IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
+};
+
+       void
+lm_mode(cmd, len, init)
+       unsigned char *cmd;
+       int len, init;
+{
+       if (len != 1)
+               return;
+       if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
+               return;
+       if (*cmd&MODE_ACK)
+               return;
+       linemode = *cmd&(MODE_MASK&~MODE_ACK);
+       str_lm_mode[4] = linemode;
+       if (!init)
+           str_lm_mode[4] |= MODE_ACK;
+       if (NETROOM() > sizeof(str_lm_mode)) {
+           ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
+           printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
+       }
+/*@*/  else printf("lm_mode: not enough room in buffer\n");
+       setconnmode(0); /* set changed mode */
+}
+
+\f
+
+/*
+ * slc()
+ * Handle special character suboption of LINEMODE.
+ */
+
+struct spc {
+       cc_t val;
+       cc_t *valp;
+       char flags;     /* Current flags & level */
+       char mylevel;   /* Maximum level & flags */
+} spc_data[NSLC+1];
+
+#define SLC_IMPORT     0
+#define        SLC_EXPORT      1
+#define SLC_RVALUE     2
+static int slc_mode = SLC_EXPORT;
+
+       void
+slc_init()
+{
+       register struct spc *spcp;
+
+       localchars = 1;
+       for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
+               spcp->val = 0;
+               spcp->valp = 0;
+               spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
+       }
+
+#define        initfunc(func, flags) { \
+                                       spcp = &spc_data[func]; \
+                                       if (spcp->valp = tcval(func)) { \
+                                           spcp->val = *spcp->valp; \
+                                           spcp->mylevel = SLC_VARIABLE|flags; \
+                                       } else { \
+                                           spcp->val = 0; \
+                                           spcp->mylevel = SLC_DEFAULT; \
+                                       } \
+                                   }
+
+       initfunc(SLC_SYNCH, 0);
+       /* No BRK */
+       initfunc(SLC_AO, 0);
+       initfunc(SLC_AYT, 0);
+       /* No EOR */
+       initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
+       initfunc(SLC_EOF, 0);
+#ifndef        SYSV_TERMIO
+       initfunc(SLC_SUSP, SLC_FLUSHIN);
+#endif
+       initfunc(SLC_EC, 0);
+       initfunc(SLC_EL, 0);
+#ifndef        SYSV_TERMIO
+       initfunc(SLC_EW, 0);
+       initfunc(SLC_RP, 0);
+       initfunc(SLC_LNEXT, 0);
+#endif
+       initfunc(SLC_XON, 0);
+       initfunc(SLC_XOFF, 0);
+#ifdef SYSV_TERMIO
+       spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
+       spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
+#endif
+       initfunc(SLC_FORW1, 0);
+#ifdef USE_TERMIO
+       initfunc(SLC_FORW2, 0);
+       /* No FORW2 */
+#endif
+
+       initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
+#undef initfunc
+
+       if (slc_mode == SLC_EXPORT)
+               slc_export();
+       else
+               slc_import(1);
+
+}
+
+    void
+slcstate()
+{
+    printf("Special characters are %s values\n",
+               slc_mode == SLC_IMPORT ? "remote default" :
+               slc_mode == SLC_EXPORT ? "local" :
+                                        "remote");
+}
+
+    void
+slc_mode_export()
+{
+    slc_mode = SLC_EXPORT;
+    if (my_state_is_will(TELOPT_LINEMODE))
+       slc_export();
+}
+
+    void
+slc_mode_import(def)
+    int def;
+{
+    slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
+    if (my_state_is_will(TELOPT_LINEMODE))
+       slc_import(def);
+}
+
+unsigned char slc_import_val[] = {
+       IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
+};
+unsigned char slc_import_def[] = {
+       IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
+};
+
+    void
+slc_import(def)
+    int def;
+{
+    if (NETROOM() > sizeof(slc_import_val)) {
+       if (def) {
+           ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
+           printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
+       } else {
+           ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
+           printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
+       }
+    }
+/*@*/ else printf("slc_import: not enough room\n");
+}
+
+    void
+slc_export()
+{
+    register struct spc *spcp;
+
+    TerminalDefaultChars();
+
+    slc_start_reply();
+    for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+       if (spcp->mylevel != SLC_NOSUPPORT) {
+           if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+               spcp->flags = SLC_NOSUPPORT;
+           else
+               spcp->flags = spcp->mylevel;
+           if (spcp->valp)
+               spcp->val = *spcp->valp;
+           slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+       }
+    }
+    slc_end_reply();
+    (void)slc_update();
+    setconnmode(1);    /* Make sure the character values are set */
+}
+
+       void
+slc(cp, len)
+       register unsigned char *cp;
+       int len;
+{
+       register struct spc *spcp;
+       register int func,level;
+
+       slc_start_reply();
+
+       for (; len >= 3; len -=3, cp +=3) {
+
+               func = cp[SLC_FUNC];
+
+               if (func == 0) {
+                       /*
+                        * Client side: always ignore 0 function.
+                        */
+                       continue;
+               }
+               if (func > NSLC) {
+                       if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
+                               slc_add_reply(func, SLC_NOSUPPORT, 0);
+                       continue;
+               }
+
+               spcp = &spc_data[func];
+
+               level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
+
+               if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
+                   ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
+                       continue;
+               }
+
+               if (level == (SLC_DEFAULT|SLC_ACK)) {
+                       /*
+                        * This is an error condition, the SLC_ACK
+                        * bit should never be set for the SLC_DEFAULT
+                        * level.  Our best guess to recover is to
+                        * ignore the SLC_ACK bit.
+                        */
+                       cp[SLC_FLAGS] &= ~SLC_ACK;
+               }
+
+               if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
+                       spcp->val = (cc_t)cp[SLC_VALUE];
+                       spcp->flags = cp[SLC_FLAGS];    /* include SLC_ACK */
+                       continue;
+               }
+
+               level &= ~SLC_ACK;
+
+               if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
+                       spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
+                       spcp->val = (cc_t)cp[SLC_VALUE];
+               }
+               if (level == SLC_DEFAULT) {
+                       if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
+                               spcp->flags = spcp->mylevel;
+                       else
+                               spcp->flags = SLC_NOSUPPORT;
+               }
+               slc_add_reply(func, spcp->flags, spcp->val);
+       }
+       slc_end_reply();
+       if (slc_update())
+               setconnmode(1); /* set the  new character values */
+}
+
+    void
+slc_check()
+{
+    register struct spc *spcp;
+
+    slc_start_reply();
+    for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+       if (spcp->valp && spcp->val != *spcp->valp) {
+           spcp->val = *spcp->valp;
+           if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+               spcp->flags = SLC_NOSUPPORT;
+           else
+               spcp->flags = spcp->mylevel;
+           slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+       }
+    }
+    slc_end_reply();
+    setconnmode(1);
+}
+
+
+unsigned char slc_reply[128];
+unsigned char *slc_replyp;
+
+       void
+slc_start_reply()
+{
+       slc_replyp = slc_reply;
+       *slc_replyp++ = IAC;
+       *slc_replyp++ = SB;
+       *slc_replyp++ = TELOPT_LINEMODE;
+       *slc_replyp++ = LM_SLC;
+}
+
+       void
+slc_add_reply(func, flags, value)
+       unsigned char func;
+       unsigned char flags;
+       cc_t value;
+{
+       if ((*slc_replyp++ = func) == IAC)
+               *slc_replyp++ = IAC;
+       if ((*slc_replyp++ = flags) == IAC)
+               *slc_replyp++ = IAC;
+       if ((*slc_replyp++ = (unsigned char)value) == IAC)
+               *slc_replyp++ = IAC;
+}
+
+    void
+slc_end_reply()
+{
+    register int len;
+
+    *slc_replyp++ = IAC;
+    *slc_replyp++ = SE;
+    len = slc_replyp - slc_reply;
+    if (len <= 6)
+       return;
+    if (NETROOM() > len) {
+       ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
+       printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
+    }
+/*@*/else printf("slc_end_reply: not enough room\n");
+}
+
+       int
+slc_update()
+{
+       register struct spc *spcp;
+       int need_update = 0;
+
+       for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+               if (!(spcp->flags&SLC_ACK))
+                       continue;
+               spcp->flags &= ~SLC_ACK;
+               if (spcp->valp && (*spcp->valp != spcp->val)) {
+                       *spcp->valp = spcp->val;
+                       need_update = 1;
+               }
+       }
+       return(need_update);
+}
+
+#ifdef OLD_ENVIRON
+# ifdef        ENV_HACK
+/*
+ * Earlier version of telnet/telnetd from the BSD code had
+ * the definitions of VALUE and VAR reversed.  To ensure
+ * maximum interoperability, we assume that the server is
+ * an older BSD server, until proven otherwise.  The newer
+ * BSD servers should be able to handle either definition,
+ * so it is better to use the wrong values if we don't
+ * know what type of server it is.
+ */
+int env_auto = 1;
+int old_env_var = OLD_ENV_VAR;
+int old_env_value = OLD_ENV_VALUE;
+# else
+#  define old_env_var OLD_ENV_VAR
+#  define old_env_value OLD_ENV_VALUE
+# endif
+#endif
+
+       void
+env_opt(buf, len)
+       register unsigned char *buf;
+       register int len;
+{
+       register unsigned char *ep = 0, *epc = 0;
+       register int i;
+
+       switch(buf[0]&0xff) {
+       case TELQUAL_SEND:
+               env_opt_start();
+               if (len == 1) {
+                       env_opt_add(NULL);
+               } else for (i = 1; i < len; i++) {
+                       switch (buf[i]&0xff) {
+#ifdef OLD_ENVIRON
+                       case OLD_ENV_VAR:
+# ifdef        ENV_HACK
+                               if (telopt_environ == TELOPT_OLD_ENVIRON
+                                   && env_auto) {
+                                       /* Server has the same definitions */
+                                       old_env_var = OLD_ENV_VAR;
+                                       old_env_value = OLD_ENV_VALUE;
+                               }
+                               /* FALL THROUGH */
+# endif
+                       case OLD_ENV_VALUE:
+                               /*
+                                * Although OLD_ENV_VALUE is not legal, we will
+                                * still recognize it, just in case it is an
+                                * old server that has VAR & VALUE mixed up...
+                                */
+                               /* FALL THROUGH */
+#else
+                       case NEW_ENV_VAR:
+#endif
+                       case ENV_USERVAR:
+                               if (ep) {
+                                       *epc = 0;
+                                       env_opt_add(ep);
+                               }
+                               ep = epc = &buf[i+1];
+                               break;
+                       case ENV_ESC:
+                               i++;
+                               /*FALL THROUGH*/
+                       default:
+                               if (epc)
+                                       *epc++ = buf[i];
+                               break;
+                       }
+               }
+               if (ep) {
+                       *epc = 0;
+                       env_opt_add(ep);
+               }
+               env_opt_end(1);
+               break;
+
+       case TELQUAL_IS:
+       case TELQUAL_INFO:
+               /* Ignore for now.  We shouldn't get it anyway. */
+               break;
+
+       default:
+               break;
+       }
+}
+
+#define        OPT_REPLY_SIZE  256
+unsigned char *opt_reply;
+unsigned char *opt_replyp;
+unsigned char *opt_replyend;
+
+       void
+env_opt_start()
+{
+       if (opt_reply)
+               opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
+       else
+               opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE);
+       if (opt_reply == NULL) {
+/*@*/          printf("env_opt_start: malloc()/realloc() failed!!!\n");
+               opt_reply = opt_replyp = opt_replyend = NULL;
+               return;
+       }
+       opt_replyp = opt_reply;
+       opt_replyend = opt_reply + OPT_REPLY_SIZE;
+       *opt_replyp++ = IAC;
+       *opt_replyp++ = SB;
+       *opt_replyp++ = telopt_environ;
+       *opt_replyp++ = TELQUAL_IS;
+}
+
+       void
+env_opt_start_info()
+{
+       env_opt_start();
+       if (opt_replyp)
+           opt_replyp[-1] = TELQUAL_INFO;
+}
+
+       void
+env_opt_add(ep)
+       register unsigned char *ep;
+{
+       register unsigned char *vp, c;
+
+       if (opt_reply == NULL)          /*XXX*/
+               return;                 /*XXX*/
+
+       if (ep == NULL || *ep == '\0') {
+               /* Send user defined variables first. */
+               env_default(1, 0);
+               while (ep = env_default(0, 0))
+                       env_opt_add(ep);
+
+               /* Now add the list of well know variables.  */
+               env_default(1, 1);
+               while (ep = env_default(0, 1))
+                       env_opt_add(ep);
+               return;
+       }
+       vp = env_getvalue(ep);
+       if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
+                               strlen((char *)ep) + 6 > opt_replyend)
+       {
+               register int len;
+               opt_replyend += OPT_REPLY_SIZE;
+               len = opt_replyend - opt_reply;
+               opt_reply = (unsigned char *)realloc(opt_reply, len);
+               if (opt_reply == NULL) {
+/*@*/                  printf("env_opt_add: realloc() failed!!!\n");
+                       opt_reply = opt_replyp = opt_replyend = NULL;
+                       return;
+               }
+               opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
+               opt_replyend = opt_reply + len;
+       }
+       if (opt_welldefined(ep))
+#ifdef OLD_ENVIRON
+               if (telopt_environ == TELOPT_OLD_ENVIRON)
+                       *opt_replyp++ = old_env_var;
+               else
+#endif
+                       *opt_replyp++ = NEW_ENV_VAR;
+       else
+               *opt_replyp++ = ENV_USERVAR;
+       for (;;) {
+               while (c = *ep++) {
+                       switch(c&0xff) {
+                       case IAC:
+                               *opt_replyp++ = IAC;
+                               break;
+                       case NEW_ENV_VAR:
+                       case NEW_ENV_VALUE:
+                       case ENV_ESC:
+                       case ENV_USERVAR:
+                               *opt_replyp++ = ENV_ESC;
+                               break;
+                       }
+                       *opt_replyp++ = c;
+               }
+               if (ep = vp) {
+#ifdef OLD_ENVIRON
+                       if (telopt_environ == TELOPT_OLD_ENVIRON)
+                               *opt_replyp++ = old_env_value;
+                       else
+#endif
+                               *opt_replyp++ = NEW_ENV_VALUE;
+                       vp = NULL;
+               } else
+                       break;
+       }
+}
+
+       int
+opt_welldefined(ep)
+       char *ep;
+{
+       if ((strcmp(ep, "USER") == 0) ||
+           (strcmp(ep, "DISPLAY") == 0) ||
+           (strcmp(ep, "PRINTER") == 0) ||
+           (strcmp(ep, "SYSTEMTYPE") == 0) ||
+           (strcmp(ep, "JOB") == 0) ||
+           (strcmp(ep, "ACCT") == 0))
+               return(1);
+       return(0);
+}
+       void
+env_opt_end(emptyok)
+       register int emptyok;
+{
+       register int len;
+
+       len = opt_replyp - opt_reply + 2;
+       if (emptyok || len > 6) {
+               *opt_replyp++ = IAC;
+               *opt_replyp++ = SE;
+               if (NETROOM() > len) {
+                       ring_supply_data(&netoring, opt_reply, len);
+                       printsub('>', &opt_reply[2], len - 2);
+               }
+/*@*/          else printf("slc_end_reply: not enough room\n");
+       }
+       if (opt_reply) {
+               free(opt_reply);
+               opt_reply = opt_replyp = opt_replyend = NULL;
+       }
+}
+
+\f
+
+    int
+telrcv()
+{
+    register int c;
+    register int scc;
+    register unsigned char *sbp;
+    int count;
+    int returnValue = 0;
+
+    scc = 0;
+    count = 0;
+    while (TTYROOM() > 2) {
+       if (scc == 0) {
+           if (count) {
+               ring_consumed(&netiring, count);
+               returnValue = 1;
+               count = 0;
+           }
+           sbp = netiring.consume;
+           scc = ring_full_consecutive(&netiring);
+           if (scc == 0) {
+               /* No more data coming in */
+               break;
+           }
+       }
+
+       c = *sbp++ & 0xff, scc--; count++;
+#ifdef ENCRYPTION
+       if (decrypt_input)
+               c = (*decrypt_input)(c);
+#endif /* ENCRYPTION */
+
+       switch (telrcv_state) {
+
+       case TS_CR:
+           telrcv_state = TS_DATA;
+           if (c == '\0') {
+               break;  /* Ignore \0 after CR */
+           }
+           else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
+               TTYADD(c);
+               break;
+           }
+           /* Else, fall through */
+
+       case TS_DATA:
+           if (c == IAC) {
+               telrcv_state = TS_IAC;
+               break;
+           }
+#          if defined(TN3270)
+           if (In3270) {
+               *Ifrontp++ = c;
+               while (scc > 0) {
+                   c = *sbp++ & 0377, scc--; count++;
+#ifdef ENCRYPTION
+                   if (decrypt_input)
+                       c = (*decrypt_input)(c);
+#endif /* ENCRYPTION */
+                   if (c == IAC) {
+                       telrcv_state = TS_IAC;
+                       break;
+                   }
+                   *Ifrontp++ = c;
+               }
+           } else
+#          endif /* defined(TN3270) */
+                   /*
+                    * The 'crmod' hack (see following) is needed
+                    * since we can't * set CRMOD on output only.
+                    * Machines like MULTICS like to send \r without
+                    * \n; since we must turn off CRMOD to get proper
+                    * input, the mapping is done here (sigh).
+                    */
+           if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
+               if (scc > 0) {
+                   c = *sbp&0xff;
+#ifdef ENCRYPTION
+                   if (decrypt_input)
+                       c = (*decrypt_input)(c);
+#endif /* ENCRYPTION */
+                   if (c == 0) {
+                       sbp++, scc--; count++;
+                       /* a "true" CR */
+                       TTYADD('\r');
+                   } else if (my_want_state_is_dont(TELOPT_ECHO) &&
+                                       (c == '\n')) {
+                       sbp++, scc--; count++;
+                       TTYADD('\n');
+                   } else {
+#ifdef ENCRYPTION
+                       if (decrypt_input)
+                           (*decrypt_input)(-1);
+#endif /* ENCRYPTION */
+
+                       TTYADD('\r');
+                       if (crmod) {
+                               TTYADD('\n');
+                       }
+                   }
+               } else {
+                   telrcv_state = TS_CR;
+                   TTYADD('\r');
+                   if (crmod) {
+                           TTYADD('\n');
+                   }
+               }
+           } else {
+               TTYADD(c);
+           }
+           continue;
+
+       case TS_IAC:
+process_iac:
+           switch (c) {
+
+           case WILL:
+               telrcv_state = TS_WILL;
+               continue;
+
+           case WONT:
+               telrcv_state = TS_WONT;
+               continue;
+
+           case DO:
+               telrcv_state = TS_DO;
+               continue;
+
+           case DONT:
+               telrcv_state = TS_DONT;
+               continue;
+
+           case DM:
+                   /*
+                    * We may have missed an urgent notification,
+                    * so make sure we flush whatever is in the
+                    * buffer currently.
+                    */
+               printoption("RCVD", IAC, DM);
+               SYNCHing = 1;
+               (void) ttyflush(1);
+               SYNCHing = stilloob();
+               settimer(gotDM);
+               break;
+
+           case SB:
+               SB_CLEAR();
+               telrcv_state = TS_SB;
+               continue;
+
+#          if defined(TN3270)
+           case EOR:
+               if (In3270) {
+                   if (Ibackp == Ifrontp) {
+                       Ibackp = Ifrontp = Ibuf;
+                       ISend = 0;      /* should have been! */
+                   } else {
+                       Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
+                       ISend = 1;
+                   }
+               }
+               printoption("RCVD", IAC, EOR);
+               break;
+#          endif /* defined(TN3270) */
+
+           case IAC:
+#          if !defined(TN3270)
+               TTYADD(IAC);
+#          else /* !defined(TN3270) */
+               if (In3270) {
+                   *Ifrontp++ = IAC;
+               } else {
+                   TTYADD(IAC);
+               }
+#          endif /* !defined(TN3270) */
+               break;
+
+           case NOP:
+           case GA:
+           default:
+               printoption("RCVD", IAC, c);
+               break;
+           }
+           telrcv_state = TS_DATA;
+           continue;
+
+       case TS_WILL:
+           printoption("RCVD", WILL, c);
+           willoption(c);
+           SetIn3270();
+           telrcv_state = TS_DATA;
+           continue;
+
+       case TS_WONT:
+           printoption("RCVD", WONT, c);
+           wontoption(c);
+           SetIn3270();
+           telrcv_state = TS_DATA;
+           continue;
+
+       case TS_DO:
+           printoption("RCVD", DO, c);
+           dooption(c);
+           SetIn3270();
+           if (c == TELOPT_NAWS) {
+               sendnaws();
+           } else if (c == TELOPT_LFLOW) {
+               localflow = 1;
+               setcommandmode();
+               setconnmode(0);
+           }
+           telrcv_state = TS_DATA;
+           continue;
+
+       case TS_DONT:
+           printoption("RCVD", DONT, c);
+           dontoption(c);
+           flushline = 1;
+           setconnmode(0);     /* set new tty mode (maybe) */
+           SetIn3270();
+           telrcv_state = TS_DATA;
+           continue;
+
+       case TS_SB:
+           if (c == IAC) {
+               telrcv_state = TS_SE;
+           } else {
+               SB_ACCUM(c);
+           }
+           continue;
+
+       case TS_SE:
+           if (c != SE) {
+               if (c != IAC) {
+                   /*
+                    * This is an error.  We only expect to get
+                    * "IAC IAC" or "IAC SE".  Several things may
+                    * have happend.  An IAC was not doubled, the
+                    * IAC SE was left off, or another option got
+                    * inserted into the suboption are all possibilities.
+                    * If we assume that the IAC was not doubled,
+                    * and really the IAC SE was left off, we could
+                    * get into an infinate loop here.  So, instead,
+                    * we terminate the suboption, and process the
+                    * partial suboption if we can.
+                    */
+                   SB_ACCUM(IAC);
+                   SB_ACCUM(c);
+                   subpointer -= 2;
+                   SB_TERM();
+
+                   printoption("In SUBOPTION processing, RCVD", IAC, c);
+                   suboption();        /* handle sub-option */
+                   SetIn3270();
+                   telrcv_state = TS_IAC;
+                   goto process_iac;
+               }
+               SB_ACCUM(c);
+               telrcv_state = TS_SB;
+           } else {
+               SB_ACCUM(IAC);
+               SB_ACCUM(SE);
+               subpointer -= 2;
+               SB_TERM();
+               suboption();    /* handle sub-option */
+               SetIn3270();
+               telrcv_state = TS_DATA;
+           }
+       }
+    }
+    if (count)
+       ring_consumed(&netiring, count);
+    return returnValue||count;
+}
+
+static int bol = 1, local = 0;
+
+    int
+rlogin_susp()
+{
+    if (local) {
+       local = 0;
+       bol = 1;
+       command(0, "z\n", 2);
+       return(1);
+    }
+    return(0);
+}
+
+    static int
+telsnd()
+{
+    int tcc;
+    int count;
+    int returnValue = 0;
+    unsigned char *tbp;
+
+    tcc = 0;
+    count = 0;
+    while (NETROOM() > 2) {
+       register int sc;
+       register int c;
+
+       if (tcc == 0) {
+           if (count) {
+               ring_consumed(&ttyiring, count);
+               returnValue = 1;
+               count = 0;
+           }
+           tbp = ttyiring.consume;
+           tcc = ring_full_consecutive(&ttyiring);
+           if (tcc == 0) {
+               break;
+           }
+       }
+       c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
+       if (rlogin != _POSIX_VDISABLE) {
+               if (bol) {
+                       bol = 0;
+                       if (sc == rlogin) {
+                               local = 1;
+                               continue;
+                       }
+               } else if (local) {
+                       local = 0;
+                       if (sc == '.' || c == termEofChar) {
+                               bol = 1;
+                               command(0, "close\n", 6);
+                               continue;
+                       }
+                       if (sc == termSuspChar) {
+                               bol = 1;
+                               command(0, "z\n", 2);
+                               continue;
+                       }
+                       if (sc == escape) {
+                               command(0, (char *)tbp, tcc);
+                               bol = 1;
+                               count += tcc;
+                               tcc = 0;
+                               flushline = 1;
+                               break;
+                       }
+                       if (sc != rlogin) {
+                               ++tcc;
+                               --tbp;
+                               --count;
+                               c = sc = rlogin;
+                       }
+               }
+               if ((sc == '\n') || (sc == '\r'))
+                       bol = 1;
+       } else if (sc == escape) {
+           /*
+            * Double escape is a pass through of a single escape character.
+            */
+           if (tcc && strip(*tbp) == escape) {
+               tbp++;
+               tcc--;
+               count++;
+               bol = 0;
+           } else {
+               command(0, (char *)tbp, tcc);
+               bol = 1;
+               count += tcc;
+               tcc = 0;
+               flushline = 1;
+               break;
+           }
+       } else
+           bol = 0;
+#ifdef KLUDGELINEMODE
+       if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
+           if (tcc > 0 && strip(*tbp) == echoc) {
+               tcc--; tbp++; count++;
+           } else {
+               dontlecho = !dontlecho;
+               settimer(echotoggle);
+               setconnmode(0);
+               flushline = 1;
+               break;
+           }
+       }
+#endif
+       if (MODE_LOCAL_CHARS(globalmode)) {
+           if (TerminalSpecialChars(sc) == 0) {
+               bol = 1;
+               break;
+           }
+       }
+       if (my_want_state_is_wont(TELOPT_BINARY)) {
+           switch (c) {
+           case '\n':
+                   /*
+                    * If we are in CRMOD mode (\r ==> \n)
+                    * on our local machine, then probably
+                    * a newline (unix) is CRLF (TELNET).
+                    */
+               if (MODE_LOCAL_CHARS(globalmode)) {
+                   NETADD('\r');
+               }
+               NETADD('\n');
+               bol = flushline = 1;
+               break;
+           case '\r':
+               if (!crlf) {
+                   NET2ADD('\r', '\0');
+               } else {
+                   NET2ADD('\r', '\n');
+               }
+               bol = flushline = 1;
+               break;
+           case IAC:
+               NET2ADD(IAC, IAC);
+               break;
+           default:
+               NETADD(c);
+               break;
+           }
+       } else if (c == IAC) {
+           NET2ADD(IAC, IAC);
+       } else {
+           NETADD(c);
+       }
+    }
+    if (count)
+       ring_consumed(&ttyiring, count);
+    return returnValue||count;         /* Non-zero if we did anything */
+}
+\f
+/*
+ * Scheduler()
+ *
+ * Try to do something.
+ *
+ * If we do something useful, return 1; else return 0.
+ *
+ */
+
+
+    int
+Scheduler(block)
+    int        block;                  /* should we block in the select ? */
+{
+               /* One wants to be a bit careful about setting returnValue
+                * to one, since a one implies we did some useful work,
+                * and therefore probably won't be called to block next
+                * time (TN3270 mode only).
+                */
+    int returnValue;
+    int netin, netout, netex, ttyin, ttyout;
+
+    /* Decide which rings should be processed */
+
+    netout = ring_full_count(&netoring) &&
+           (flushline ||
+               (my_want_state_is_wont(TELOPT_LINEMODE)
+#ifdef KLUDGELINEMODE
+                       && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
+#endif
+               ) ||
+                       my_want_state_is_will(TELOPT_BINARY));
+    ttyout = ring_full_count(&ttyoring);
+
+#if    defined(TN3270)
+    ttyin = ring_empty_count(&ttyiring) && (shell_active == 0);
+#else  /* defined(TN3270) */
+    ttyin = ring_empty_count(&ttyiring);
+#endif /* defined(TN3270) */
+
+#if    defined(TN3270)
+    netin = ring_empty_count(&netiring);
+#   else /* !defined(TN3270) */
+    netin = !ISend && ring_empty_count(&netiring);
+#   endif /* !defined(TN3270) */
+
+    netex = !SYNCHing;
+
+    /* If we have seen a signal recently, reset things */
+#   if defined(TN3270) && (defined(unix) || defined(__APPLE__))
+    if (HaveInput) {
+       HaveInput = 0;
+       (void) signal(SIGIO, inputAvailable);
+    }
+#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */
+
+    /* Call to system code to process rings */
+
+    returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
+
+    /* Now, look at the input rings, looking for work to do. */
+
+    if (ring_full_count(&ttyiring)) {
+#   if defined(TN3270)
+       if (In3270) {
+           int c;
+
+           c = DataFromTerminal(ttyiring.consume,
+                                       ring_full_consecutive(&ttyiring));
+           if (c) {
+               returnValue = 1;
+               ring_consumed(&ttyiring, c);
+           }
+       } else {
+#   endif /* defined(TN3270) */
+           returnValue |= telsnd();
+#   if defined(TN3270)
+       }
+#   endif /* defined(TN3270) */
+    }
+
+    if (ring_full_count(&netiring)) {
+#      if !defined(TN3270)
+       returnValue |= telrcv();
+#      else /* !defined(TN3270) */
+       returnValue = Push3270();
+#      endif /* !defined(TN3270) */
+    }
+    return returnValue;
+}
+\f
+/*
+ * Select from tty and network...
+ */
+    void
+telnet(user)
+    char *user;
+{
+    sys_telnet_init();
+
+#if    defined(AUTHENTICATION) || defined(ENCRYPTION)
+    {
+       static char local_host[256] = { 0 };
+
+       if (!local_host[0]) {
+               gethostname(local_host, sizeof(local_host));
+               local_host[sizeof(local_host)-1] = 0;
+       }
+       auth_encrypt_init(local_host, hostname, "TELNET", 0);
+       auth_encrypt_user(user);
+    }
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION)  */
+#   if !defined(TN3270)
+    if (telnetport) {
+#if    defined(AUTHENTICATION)
+       if (autologin)
+               send_will(TELOPT_AUTHENTICATION, 1);
+#endif
+#ifdef ENCRYPTION
+       send_do(TELOPT_ENCRYPT, 1);
+       send_will(TELOPT_ENCRYPT, 1);
+#endif /* ENCRYPTION */
+       send_do(TELOPT_SGA, 1);
+       send_will(TELOPT_TTYPE, 1);
+       send_will(TELOPT_NAWS, 1);
+       send_will(TELOPT_TSPEED, 1);
+       send_will(TELOPT_LFLOW, 1);
+       send_will(TELOPT_LINEMODE, 1);
+       send_will(TELOPT_NEW_ENVIRON, 1);
+       send_do(TELOPT_STATUS, 1);
+       if (env_getvalue((unsigned char *)"DISPLAY"))
+           send_will(TELOPT_XDISPLOC, 1);
+       if (eight)
+           tel_enter_binary(eight);
+    }
+#   endif /* !defined(TN3270) */
+
+#   if !defined(TN3270)
+    for (;;) {
+       int schedValue;
+
+       while ((schedValue = Scheduler(0)) != 0) {
+           if (schedValue == -1) {
+               setcommandmode();
+               return;
+           }
+       }
+
+       if (Scheduler(1) == -1) {
+           setcommandmode();
+           return;
+       }
+    }
+#   else /* !defined(TN3270) */
+    for (;;) {
+       int schedValue;
+
+       while (!In3270 && !shell_active) {
+           if (Scheduler(1) == -1) {
+               setcommandmode();
+               return;
+           }
+       }
+
+       while ((schedValue = Scheduler(0)) != 0) {
+           if (schedValue == -1) {
+               setcommandmode();
+               return;
+           }
+       }
+               /* If there is data waiting to go out to terminal, don't
+                * schedule any more data for the terminal.
+                */
+       if (ring_full_count(&ttyoring)) {
+           schedValue = 1;
+       } else {
+           if (shell_active) {
+               if (shell_continue() == 0) {
+                   ConnectScreen();
+               }
+           } else if (In3270) {
+               schedValue = DoTerminalOutput();
+           }
+       }
+       if (schedValue && (shell_active == 0)) {
+           if (Scheduler(1) == -1) {
+               setcommandmode();
+               return;
+           }
+       }
+    }
+#   endif /* !defined(TN3270) */
+}
+\f
+#if    0       /* XXX - this not being in is a bug */
+/*
+ * nextitem()
+ *
+ *     Return the address of the next "item" in the TELNET data
+ * stream.  This will be the address of the next character if
+ * the current address is a user data character, or it will
+ * be the address of the character following the TELNET command
+ * if the current address is a TELNET IAC ("I Am a Command")
+ * character.
+ */
+
+    static char *
+nextitem(current)
+    char *current;
+{
+    if ((*current&0xff) != IAC) {
+       return current+1;
+    }
+    switch (*(current+1)&0xff) {
+    case DO:
+    case DONT:
+    case WILL:
+    case WONT:
+       return current+3;
+    case SB:           /* loop forever looking for the SE */
+       {
+           register char *look = current+2;
+
+           for (;;) {
+               if ((*look++&0xff) == IAC) {
+                   if ((*look++&0xff) == SE) {
+                       return look;
+                   }
+               }
+           }
+       }
+    default:
+       return current+2;
+    }
+}
+#endif /* 0 */
+
+/*
+ * netclear()
+ *
+ *     We are about to do a TELNET SYNCH operation.  Clear
+ * the path to the network.
+ *
+ *     Things are a bit tricky since we may have sent the first
+ * byte or so of a previous TELNET command into the network.
+ * So, we have to scan the network buffer from the beginning
+ * until we are up to where we want to be.
+ *
+ *     A side effect of what we do, just to keep things
+ * simple, is to clear the urgent data pointer.  The principal
+ * caller should be setting the urgent data pointer AFTER calling
+ * us in any case.
+ */
+
+    static void
+netclear()
+{
+#if    0       /* XXX */
+    register char *thisitem, *next;
+    char *good;
+#define        wewant(p)       ((nfrontp > p) && ((*p&0xff) == IAC) && \
+                               ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+
+    thisitem = netobuf;
+
+    while ((next = nextitem(thisitem)) <= netobuf.send) {
+       thisitem = next;
+    }
+
+    /* Now, thisitem is first before/at boundary. */
+
+    good = netobuf;    /* where the good bytes go */
+
+    while (netoring.add > thisitem) {
+       if (wewant(thisitem)) {
+           int length;
+
+           next = thisitem;
+           do {
+               next = nextitem(next);
+           } while (wewant(next) && (nfrontp > next));
+           length = next-thisitem;
+           memmove(good, thisitem, length);
+           good += length;
+           thisitem = next;
+       } else {
+           thisitem = nextitem(thisitem);
+       }
+    }
+
+#endif /* 0 */
+}
+\f
+/*
+ * These routines add various telnet commands to the data stream.
+ */
+
+    static void
+doflush()
+{
+    NET2ADD(IAC, DO);
+    NETADD(TELOPT_TM);
+    flushline = 1;
+    flushout = 1;
+    (void) ttyflush(1);                        /* Flush/drop output */
+    /* do printoption AFTER flush, otherwise the output gets tossed... */
+    printoption("SENT", DO, TELOPT_TM);
+}
+
+    void
+xmitAO()
+{
+    NET2ADD(IAC, AO);
+    printoption("SENT", IAC, AO);
+    if (autoflush) {
+       doflush();
+    }
+}
+
+
+    void
+xmitEL()
+{
+    NET2ADD(IAC, EL);
+    printoption("SENT", IAC, EL);
+}
+
+    void
+xmitEC()
+{
+    NET2ADD(IAC, EC);
+    printoption("SENT", IAC, EC);
+}
+
+
+    int
+dosynch()
+{
+    netclear();                        /* clear the path to the network */
+    NETADD(IAC);
+    setneturg();
+    NETADD(DM);
+    printoption("SENT", IAC, DM);
+    return 1;
+}
+
+int want_status_response = 0;
+
+    int
+get_status()
+{
+    unsigned char tmp[16];
+    register unsigned char *cp;
+
+    if (my_want_state_is_dont(TELOPT_STATUS)) {
+       printf("Remote side does not support STATUS option\n");
+       return 0;
+    }
+    cp = tmp;
+
+    *cp++ = IAC;
+    *cp++ = SB;
+    *cp++ = TELOPT_STATUS;
+    *cp++ = TELQUAL_SEND;
+    *cp++ = IAC;
+    *cp++ = SE;
+    if (NETROOM() >= cp - tmp) {
+       ring_supply_data(&netoring, tmp, cp-tmp);
+       printsub('>', tmp+2, cp - tmp - 2);
+    }
+    ++want_status_response;
+    return 1;
+}
+
+    void
+intp()
+{
+    NET2ADD(IAC, IP);
+    printoption("SENT", IAC, IP);
+    flushline = 1;
+    if (autoflush) {
+       doflush();
+    }
+    if (autosynch) {
+       dosynch();
+    }
+}
+
+    void
+sendbrk()
+{
+    NET2ADD(IAC, BREAK);
+    printoption("SENT", IAC, BREAK);
+    flushline = 1;
+    if (autoflush) {
+       doflush();
+    }
+    if (autosynch) {
+       dosynch();
+    }
+}
+
+    void
+sendabort()
+{
+    NET2ADD(IAC, ABORT);
+    printoption("SENT", IAC, ABORT);
+    flushline = 1;
+    if (autoflush) {
+       doflush();
+    }
+    if (autosynch) {
+       dosynch();
+    }
+}
+
+    void
+sendsusp()
+{
+    NET2ADD(IAC, SUSP);
+    printoption("SENT", IAC, SUSP);
+    flushline = 1;
+    if (autoflush) {
+       doflush();
+    }
+    if (autosynch) {
+       dosynch();
+    }
+}
+
+    void
+sendeof()
+{
+    NET2ADD(IAC, xEOF);
+    printoption("SENT", IAC, xEOF);
+}
+
+    void
+sendayt()
+{
+    NET2ADD(IAC, AYT);
+    printoption("SENT", IAC, AYT);
+}
+
+/*
+ * Send a window size update to the remote system.
+ */
+
+    void
+sendnaws()
+{
+    long rows, cols;
+    unsigned char tmp[16];
+    register unsigned char *cp;
+
+    if (my_state_is_wont(TELOPT_NAWS))
+       return;
+
+#define        PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
+                           if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
+
+    if (TerminalWindowSize(&rows, &cols) == 0) {       /* Failed */
+       return;
+    }
+
+    cp = tmp;
+
+    *cp++ = IAC;
+    *cp++ = SB;
+    *cp++ = TELOPT_NAWS;
+    PUTSHORT(cp, cols);
+    PUTSHORT(cp, rows);
+    *cp++ = IAC;
+    *cp++ = SE;
+    if (NETROOM() >= cp - tmp) {
+       ring_supply_data(&netoring, tmp, cp-tmp);
+       printsub('>', tmp+2, cp - tmp - 2);
+    }
+}
+
+    void
+tel_enter_binary(rw)
+    int rw;
+{
+    if (rw&1)
+       send_do(TELOPT_BINARY, 1);
+    if (rw&2)
+       send_will(TELOPT_BINARY, 1);
+}
+
+    void
+tel_leave_binary(rw)
+    int rw;
+{
+    if (rw&1)
+       send_dont(TELOPT_BINARY, 1);
+    if (rw&2)
+       send_wont(TELOPT_BINARY, 1);
+}
diff --git a/telnet.tproj/terminal.c b/telnet.tproj/terminal.c
new file mode 100644 (file)
index 0000000..de75e4d
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)terminal.c 8.2 (Berkeley) 2/16/95";
+#endif /* not lint */
+
+#include <arpa/telnet.h>
+#include <sys/types.h>
+
+#include "ring.h"
+
+#include "externs.h"
+#include "types.h"
+
+Ring           ttyoring, ttyiring;
+unsigned char  ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ];
+
+int termdata;                  /* Debugging flag */
+
+#ifdef USE_TERMIO
+# ifndef VDISCARD
+cc_t termFlushChar;
+# endif
+# ifndef VLNEXT
+cc_t termLiteralNextChar;
+# endif
+# ifndef VSUSP
+cc_t termSuspChar;
+# endif
+# ifndef VWERASE
+cc_t termWerasChar;
+# endif
+# ifndef VREPRINT
+cc_t termRprntChar;
+# endif
+# ifndef VSTART
+cc_t termStartChar;
+# endif
+# ifndef VSTOP
+cc_t termStopChar;
+# endif
+# ifndef VEOL
+cc_t termForw1Char;
+# endif
+# ifndef VEOL2
+cc_t termForw2Char;
+# endif
+# ifndef VSTATUS
+cc_t termAytChar;
+# endif
+#else
+cc_t termForw2Char;
+cc_t termAytChar;
+#endif
+
+/*
+ * initialize the terminal data structures.
+ */
+
+    void
+init_terminal()
+{
+    if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) {
+       exit(1);
+    }
+    if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) {
+       exit(1);
+    }
+    autoflush = TerminalAutoFlush();
+}
+
+
+/*
+ *             Send as much data as possible to the terminal.
+ *
+ *             Return value:
+ *                     -1: No useful work done, data waiting to go out.
+ *                      0: No data was waiting, so nothing was done.
+ *                      1: All waiting data was written out.
+ *                      n: All data - n was written out.
+ */
+
+
+    int
+ttyflush(drop)
+    int drop;
+{
+    register int n, n0, n1;
+
+    n0 = ring_full_count(&ttyoring);
+    if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
+       if (drop) {
+           TerminalFlushOutput();
+           /* we leave 'n' alone! */
+       } else {
+           n = TerminalWrite(ttyoring.consume, n);
+       }
+    }
+    if (n > 0) {
+       if (termdata && n) {
+           Dump('>', ttyoring.consume, n);
+       }
+       /*
+        * If we wrote everything, and the full count is
+        * larger than what we wrote, then write the
+        * rest of the buffer.
+        */
+       if (n1 == n && n0 > n) {
+               n1 = n0 - n;
+               if (!drop)
+                       n1 = TerminalWrite(ttyoring.bottom, n1);
+               if (n1 > 0)
+                       n += n1;
+       }
+       ring_consumed(&ttyoring, n);
+    }
+    if (n < 0)
+       return -1;
+    if (n == n0) {
+       if (n0)
+           return -1;
+       return 0;
+    }
+    return n0 - n + 1;
+}
+
+\f
+/*
+ * These routines decides on what the mode should be (based on the values
+ * of various global variables).
+ */
+
+
+    int
+getconnmode()
+{
+    extern int linemode;
+    int mode = 0;
+#ifdef KLUDGELINEMODE
+    extern int kludgelinemode;
+#endif
+
+    if (In3270)
+       return(MODE_FLOW);
+
+    if (my_want_state_is_dont(TELOPT_ECHO))
+       mode |= MODE_ECHO;
+
+    if (localflow)
+       mode |= MODE_FLOW;
+
+    if (my_want_state_is_will(TELOPT_BINARY))
+       mode |= MODE_INBIN;
+
+    if (his_want_state_is_will(TELOPT_BINARY))
+       mode |= MODE_OUTBIN;
+
+#ifdef KLUDGELINEMODE
+    if (kludgelinemode) {
+       if (my_want_state_is_dont(TELOPT_SGA)) {
+           mode |= (MODE_TRAPSIG|MODE_EDIT);
+           if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
+               mode &= ~MODE_ECHO;
+           }
+       }
+       return(mode);
+    }
+#endif
+    if (my_want_state_is_will(TELOPT_LINEMODE))
+       mode |= linemode;
+    return(mode);
+}
+
+    void
+setconnmode(force)
+    int force;
+{
+#ifdef ENCRYPTION
+    static int enc_passwd = 0;
+#endif /* ENCRYPTION */
+    register int newmode;
+
+    newmode = getconnmode()|(force?MODE_FORCE:0);
+
+    TerminalNewMode(newmode);
+
+#ifdef  ENCRYPTION
+    if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
+       if (my_want_state_is_will(TELOPT_ENCRYPT)
+                               && (enc_passwd == 0) && !encrypt_output) {
+           encrypt_request_start(0, 0);
+           enc_passwd = 1;
+       }
+    } else {
+       if (enc_passwd) {
+           encrypt_request_end();
+           enc_passwd = 0;
+       }
+    }
+#endif /* ENCRYPTION */
+
+}
+
+
+    void
+setcommandmode()
+{
+    TerminalNewMode(-1);
+}
diff --git a/telnet.tproj/tn3270.c b/telnet.tproj/tn3270.c
new file mode 100644 (file)
index 0000000..875d386
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)tn3270.c   8.2 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <arpa/telnet.h>
+
+#include "general.h"
+
+#include "defines.h"
+#include "ring.h"
+#include "externs.h"
+#include "fdset.h"
+
+#if    defined(TN3270)
+
+#include "../ctlr/screen.h"
+#include "../general/globals.h"
+
+#include "../sys_curses/telextrn.h"
+#include "../ctlr/externs.h"
+
+#if    defined(unix) || defined(__APPLE__)
+int
+       HaveInput,              /* There is input available to scan */
+       cursesdata,             /* Do we dump curses data? */
+       sigiocount;             /* Number of times we got a SIGIO */
+
+char   tline[200];
+char   *transcom = 0;  /* transparent mode command (default: none) */
+#endif /* defined(unix) || defined(__APPLE__) */
+
+char   Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
+
+static char    sb_terminal[] = { IAC, SB,
+                       TELOPT_TTYPE, TELQUAL_IS,
+                       'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
+                       IAC, SE };
+#define        SBTERMMODEL     13
+
+static int
+       Sent3270TerminalType;   /* Have we said we are a 3270? */
+
+#endif /* defined(TN3270) */
+
+
+    void
+init_3270()
+{
+#if    defined(TN3270)
+#if    defined(unix) || defined(__APPLE__)
+    HaveInput = 0;
+    sigiocount = 0;
+#endif /* defined(unix) || defined(__APPLE__) */
+    Sent3270TerminalType = 0;
+    Ifrontp = Ibackp = Ibuf;
+    init_ctlr();               /* Initialize some things */
+    init_keyboard();
+    init_screen();
+    init_system();
+#endif /* defined(TN3270) */
+}
+
+\f
+#if    defined(TN3270)
+
+/*
+ * DataToNetwork - queue up some data to go to network.  If "done" is set,
+ * then when last byte is queued, we add on an IAC EOR sequence (so,
+ * don't call us with "done" until you want that done...)
+ *
+ * We actually do send all the data to the network buffer, since our
+ * only client needs for us to do that.
+ */
+
+    int
+DataToNetwork(buffer, count, done)
+    register char *buffer;     /* where the data is */
+    register int  count;       /* how much to send */
+    int                  done;         /* is this the last of a logical block */
+{
+    register int loop, c;
+    int origCount;
+
+    origCount = count;
+
+    while (count) {
+       /* If not enough room for EORs, IACs, etc., wait */
+       if (NETROOM() < 6) {
+           fd_set o;
+
+           FD_ZERO(&o);
+           netflush();
+           while (NETROOM() < 6) {
+               FD_SET(net, &o);
+               (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
+                                               (struct timeval *) 0);
+               netflush();
+           }
+       }
+       c = ring_empty_count(&netoring);
+       if (c > count) {
+           c = count;
+       }
+       loop = c;
+       while (loop) {
+           if (((unsigned char)*buffer) == IAC) {
+               break;
+           }
+           buffer++;
+           loop--;
+       }
+       if ((c = c-loop)) {
+           ring_supply_data(&netoring, buffer-c, c);
+           count -= c;
+       }
+       if (loop) {
+           NET2ADD(IAC, IAC);
+           count--;
+           buffer++;
+       }
+    }
+
+    if (done) {
+       NET2ADD(IAC, EOR);
+       netflush();             /* try to move along as quickly as ... */
+    }
+    return(origCount - count);
+}
+
+
+#if    defined(unix) || defined(__APPLE__)
+    void
+inputAvailable(signo)
+       int signo;
+{
+    HaveInput = 1;
+    sigiocount++;
+}
+#endif /* defined(unix) || defined(__APPLE__) */
+
+    void
+outputPurge()
+{
+    (void) ttyflush(1);
+}
+
+
+/*
+ * The following routines are places where the various tn3270
+ * routines make calls into telnet.c.
+ */
+
+/*
+ * DataToTerminal - queue up some data to go to terminal.
+ *
+ * Note: there are people who call us and depend on our processing
+ * *all* the data at one time (thus the select).
+ */
+
+    int
+DataToTerminal(buffer, count)
+    register char      *buffer;                /* where the data is */
+    register int       count;                  /* how much to send */
+{
+    register int c;
+    int origCount;
+
+    origCount = count;
+
+    while (count) {
+       if (TTYROOM() == 0) {
+#if    defined(unix) || defined(__APPLE__)
+           fd_set o;
+
+           FD_ZERO(&o);
+#endif /* defined(unix) || defined(__APPLE__) */
+           (void) ttyflush(0);
+           while (TTYROOM() == 0) {
+#if    defined(unix) || defined(__APPLE__)
+               FD_SET(tout, &o);
+               (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
+                                               (struct timeval *) 0);
+#endif /* defined(unix) || defined(__APPLE__) */
+               (void) ttyflush(0);
+           }
+       }
+       c = TTYROOM();
+       if (c > count) {
+           c = count;
+       }
+       ring_supply_data(&ttyoring, buffer, c);
+       count -= c;
+       buffer += c;
+    }
+    return(origCount);
+}
+\f
+
+/*
+ * Push3270 - Try to send data along the 3270 output (to screen) direction.
+ */
+
+    int
+Push3270()
+{
+    int save = ring_full_count(&netiring);
+
+    if (save) {
+       if (Ifrontp+save > Ibuf+sizeof Ibuf) {
+           if (Ibackp != Ibuf) {
+               memmove(Ibuf, Ibackp, Ifrontp-Ibackp);
+               Ifrontp -= (Ibackp-Ibuf);
+               Ibackp = Ibuf;
+           }
+       }
+       if (Ifrontp+save < Ibuf+sizeof Ibuf) {
+           (void)telrcv();
+       }
+    }
+    return save != ring_full_count(&netiring);
+}
+
+
+/*
+ * Finish3270 - get the last dregs of 3270 data out to the terminal
+ *             before quitting.
+ */
+
+    void
+Finish3270()
+{
+    while (Push3270() || !DoTerminalOutput()) {
+#if    defined(unix) || defined(__APPLE__)
+       HaveInput = 0;
+#endif /* defined(unix) || defined(__APPLE__) */
+       ;
+    }
+}
+
+
+/* StringToTerminal - output a null terminated string to the terminal */
+
+    void
+StringToTerminal(s)
+    char *s;
+{
+    int count;
+
+    count = strlen(s);
+    if (count) {
+       (void) DataToTerminal(s, count);        /* we know it always goes... */
+    }
+}
+
+
+#if    ((!defined(NOT43)) || defined(PUTCHAR))
+/* _putchar - output a single character to the terminal.  This name is so that
+ *     curses(3x) can call us to send out data.
+ */
+
+    void
+_putchar(c)
+    char c;
+{
+#if    defined(sun)            /* SunOS 4.0 bug */
+    c &= 0x7f;
+#endif /* defined(sun) */
+    if (cursesdata) {
+       Dump('>', &c, 1);
+    }
+    if (!TTYROOM()) {
+       (void) DataToTerminal(&c, 1);
+    } else {
+       TTYADD(c);
+    }
+}
+#endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
+
+    void
+SetIn3270()
+{
+    if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
+               && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
+       if (!In3270) {
+           In3270 = 1;
+           Init3270();         /* Initialize 3270 functions */
+           /* initialize terminal key mapping */
+           InitTerminal();     /* Start terminal going */
+           setconnmode(0);
+       }
+    } else {
+       if (In3270) {
+           StopScreen(1);
+           In3270 = 0;
+           Stop3270();         /* Tell 3270 we aren't here anymore */
+           setconnmode(0);
+       }
+    }
+}
+
+/*
+ * tn3270_ttype()
+ *
+ *     Send a response to a terminal type negotiation.
+ *
+ *     Return '0' if no more responses to send; '1' if a response sent.
+ */
+
+    int
+tn3270_ttype()
+{
+    /*
+     * Try to send a 3270 type terminal name.  Decide which one based
+     * on the format of our screen, and (in the future) color
+     * capaiblities.
+     */
+    InitTerminal();            /* Sets MaxNumberColumns, MaxNumberLines */
+    if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
+       Sent3270TerminalType = 1;
+       if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
+           MaxNumberLines = 27;
+           MaxNumberColumns = 132;
+           sb_terminal[SBTERMMODEL] = '5';
+       } else if (MaxNumberLines >= 43) {
+           MaxNumberLines = 43;
+           MaxNumberColumns = 80;
+           sb_terminal[SBTERMMODEL] = '4';
+       } else if (MaxNumberLines >= 32) {
+           MaxNumberLines = 32;
+           MaxNumberColumns = 80;
+           sb_terminal[SBTERMMODEL] = '3';
+       } else {
+           MaxNumberLines = 24;
+           MaxNumberColumns = 80;
+           sb_terminal[SBTERMMODEL] = '2';
+       }
+       NumberLines = 24;               /* before we start out... */
+       NumberColumns = 80;
+       ScreenSize = NumberLines*NumberColumns;
+       if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
+           ExitString("Programming error:  MAXSCREENSIZE too small.\n",
+                                                               1);
+           /*NOTREACHED*/
+       }
+       printsub('>', sb_terminal+2, sizeof sb_terminal-2);
+       ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+#if    defined(unix) || defined(__APPLE__)
+       int
+settranscom(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int i;
+
+       if (argc == 1 && transcom) {
+          transcom = 0;
+       }
+       if (argc == 1) {
+          return 1;
+       }
+       transcom = tline;
+       (void) strcpy(transcom, argv[1]);
+       for (i = 2; i < argc; ++i) {
+           (void) strcat(transcom, " ");
+           (void) strcat(transcom, argv[i]);
+       }
+       return 1;
+}
+#endif /* defined(unix) || defined(__APPLE__) */
+
+#endif /* defined(TN3270) */
diff --git a/telnet.tproj/types.h b/telnet.tproj/types.h
new file mode 100644 (file)
index 0000000..42b1b8f
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)types.h     8.1 (Berkeley) 6/6/93
+ */
+
+typedef struct {
+    char *modedescriptions;
+    char modetype;
+} Modelist;
+
+extern Modelist modelist[];
+
+typedef struct {
+    int
+       system,                 /* what the current time is */
+       echotoggle,             /* last time user entered echo character */
+       modenegotiated,         /* last time operating mode negotiated */
+       didnetreceive,          /* last time we read data from network */
+       gotDM;                  /* when did we last see a data mark */
+} Clocks;
+
+extern Clocks clocks;
diff --git a/telnet.tproj/utilities.c b/telnet.tproj/utilities.c
new file mode 100644 (file)
index 0000000..2957297
--- /dev/null
@@ -0,0 +1,962 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)utilities.c        8.3 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#define        TELOPTS
+#define        TELCMDS
+#define        SLC_NAMES
+#include <arpa/telnet.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+
+#include "general.h"
+
+#include "fdset.h"
+
+#include "ring.h"
+
+#include "defines.h"
+
+#include "externs.h"
+
+FILE   *NetTrace = 0;          /* Not in bss, since needs to stay */
+int    prettydump;
+
+/*
+ * upcase()
+ *
+ *     Upcase (in place) the argument.
+ */
+
+    void
+upcase(argument)
+    register char *argument;
+{
+    register int c;
+
+    while ((c = *argument) != 0) {
+       if (islower(c)) {
+           *argument = toupper(c);
+       }
+       argument++;
+    }
+}
+
+/*
+ * SetSockOpt()
+ *
+ * Compensate for differences in 4.2 and 4.3 systems.
+ */
+
+    int
+SetSockOpt(fd, level, option, yesno)
+    int fd, level, option, yesno;
+{
+#ifndef        NOT43
+    return setsockopt(fd, level, option,
+                               (char *)&yesno, sizeof yesno);
+#else  /* NOT43 */
+    if (yesno == 0) {          /* Can't do that in 4.2! */
+       fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
+                               option);
+       return -1;
+    }
+    return setsockopt(fd, level, option, 0, 0);
+#endif /* NOT43 */
+}
+\f
+/*
+ * The following are routines used to print out debugging information.
+ */
+
+unsigned char NetTraceFile[256] = "(standard output)";
+
+    void
+SetNetTrace(file)
+    register char *file;
+{
+    if (NetTrace && NetTrace != stdout)
+       fclose(NetTrace);
+    if (file  && (strcmp(file, "-") != 0)) {
+       NetTrace = fopen(file, "w");
+       if (NetTrace) {
+           strcpy((char *)NetTraceFile, file);
+           return;
+       }
+       fprintf(stderr, "Cannot open %s.\n", file);
+    }
+    NetTrace = stdout;
+    strcpy((char *)NetTraceFile, "(standard output)");
+}
+
+    void
+Dump(direction, buffer, length)
+    char direction;
+    unsigned char *buffer;
+    int length;
+{
+#   define BYTES_PER_LINE      32
+#   define min(x,y)    ((x<y)? x:y)
+    unsigned char *pThis;
+    int offset;
+    extern pettydump;
+
+    offset = 0;
+
+    while (length) {
+       /* print one line */
+       fprintf(NetTrace, "%c 0x%x\t", direction, offset);
+       pThis = buffer;
+       if (prettydump) {
+           buffer = buffer + min(length, BYTES_PER_LINE/2);
+           while (pThis < buffer) {
+               fprintf(NetTrace, "%c%.2x",
+                   (((*pThis)&0xff) == 0xff) ? '*' : ' ',
+                   (*pThis)&0xff);
+               pThis++;
+           }
+           length -= BYTES_PER_LINE/2;
+           offset += BYTES_PER_LINE/2;
+       } else {
+           buffer = buffer + min(length, BYTES_PER_LINE);
+           while (pThis < buffer) {
+               fprintf(NetTrace, "%.2x", (*pThis)&0xff);
+               pThis++;
+           }
+           length -= BYTES_PER_LINE;
+           offset += BYTES_PER_LINE;
+       }
+       if (NetTrace == stdout) {
+           fprintf(NetTrace, "\r\n");
+       } else {
+           fprintf(NetTrace, "\n");
+       }
+       if (length < 0) {
+           fflush(NetTrace);
+           return;
+       }
+       /* find next unique line */
+    }
+    fflush(NetTrace);
+}
+
+
+       void
+printoption(direction, cmd, option)
+       char *direction;
+       int cmd, option;
+{
+       if (!showoptions)
+               return;
+       if (cmd == IAC) {
+               if (TELCMD_OK(option))
+                   fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
+               else
+                   fprintf(NetTrace, "%s IAC %d", direction, option);
+       } else {
+               register char *fmt;
+               fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
+                       (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
+               if (fmt) {
+                   fprintf(NetTrace, "%s %s ", direction, fmt);
+                   if (TELOPT_OK(option))
+                       fprintf(NetTrace, "%s", TELOPT(option));
+                   else if (option == TELOPT_EXOPL)
+                       fprintf(NetTrace, "EXOPL");
+                   else
+                       fprintf(NetTrace, "%d", option);
+               } else
+                   fprintf(NetTrace, "%s %d %d", direction, cmd, option);
+       }
+       if (NetTrace == stdout) {
+           fprintf(NetTrace, "\r\n");
+           fflush(NetTrace);
+       } else {
+           fprintf(NetTrace, "\n");
+       }
+       return;
+}
+
+    void
+optionstatus()
+{
+    register int i;
+    extern char will_wont_resp[], do_dont_resp[];
+
+    for (i = 0; i < 256; i++) {
+       if (do_dont_resp[i]) {
+           if (TELOPT_OK(i))
+               printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
+           else if (TELCMD_OK(i))
+               printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
+           else
+               printf("resp DO_DONT %d: %d\n", i,
+                               do_dont_resp[i]);
+           if (my_want_state_is_do(i)) {
+               if (TELOPT_OK(i))
+                   printf("want DO   %s\n", TELOPT(i));
+               else if (TELCMD_OK(i))
+                   printf("want DO   %s\n", TELCMD(i));
+               else
+                   printf("want DO   %d\n", i);
+           } else {
+               if (TELOPT_OK(i))
+                   printf("want DONT %s\n", TELOPT(i));
+               else if (TELCMD_OK(i))
+                   printf("want DONT %s\n", TELCMD(i));
+               else
+                   printf("want DONT %d\n", i);
+           }
+       } else {
+           if (my_state_is_do(i)) {
+               if (TELOPT_OK(i))
+                   printf("     DO   %s\n", TELOPT(i));
+               else if (TELCMD_OK(i))
+                   printf("     DO   %s\n", TELCMD(i));
+               else
+                   printf("     DO   %d\n", i);
+           }
+       }
+       if (will_wont_resp[i]) {
+           if (TELOPT_OK(i))
+               printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
+           else if (TELCMD_OK(i))
+               printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
+           else
+               printf("resp WILL_WONT %d: %d\n",
+                               i, will_wont_resp[i]);
+           if (my_want_state_is_will(i)) {
+               if (TELOPT_OK(i))
+                   printf("want WILL %s\n", TELOPT(i));
+               else if (TELCMD_OK(i))
+                   printf("want WILL %s\n", TELCMD(i));
+               else
+                   printf("want WILL %d\n", i);
+           } else {
+               if (TELOPT_OK(i))
+                   printf("want WONT %s\n", TELOPT(i));
+               else if (TELCMD_OK(i))
+                   printf("want WONT %s\n", TELCMD(i));
+               else
+                   printf("want WONT %d\n", i);
+           }
+       } else {
+           if (my_state_is_will(i)) {
+               if (TELOPT_OK(i))
+                   printf("     WILL %s\n", TELOPT(i));
+               else if (TELCMD_OK(i))
+                   printf("     WILL %s\n", TELCMD(i));
+               else
+                   printf("     WILL %d\n", i);
+           }
+       }
+    }
+
+}
+
+    void
+printsub(direction, pointer, length)
+    char direction;    /* '<' or '>' */
+    unsigned char *pointer;    /* where suboption data sits */
+    int                  length;       /* length of suboption data */
+{
+    register int i;
+    char buf[512];
+    extern int want_status_response;
+
+    if (showoptions || direction == 0 ||
+       (want_status_response && (pointer[0] == TELOPT_STATUS))) {
+       if (direction) {
+           fprintf(NetTrace, "%s IAC SB ",
+                               (direction == '<')? "RCVD":"SENT");
+           if (length >= 3) {
+               register int j;
+
+               i = pointer[length-2];
+               j = pointer[length-1];
+
+               if (i != IAC || j != SE) {
+                   fprintf(NetTrace, "(terminated by ");
+                   if (TELOPT_OK(i))
+                       fprintf(NetTrace, "%s ", TELOPT(i));
+                   else if (TELCMD_OK(i))
+                       fprintf(NetTrace, "%s ", TELCMD(i));
+                   else
+                       fprintf(NetTrace, "%d ", i);
+                   if (TELOPT_OK(j))
+                       fprintf(NetTrace, "%s", TELOPT(j));
+                   else if (TELCMD_OK(j))
+                       fprintf(NetTrace, "%s", TELCMD(j));
+                   else
+                       fprintf(NetTrace, "%d", j);
+                   fprintf(NetTrace, ", not IAC SE!) ");
+               }
+           }
+           length -= 2;
+       }
+       if (length < 1) {
+           fprintf(NetTrace, "(Empty suboption??\?)");
+           if (NetTrace == stdout)
+               fflush(NetTrace);
+           return;
+       }
+       switch (pointer[0]) {
+       case TELOPT_TTYPE:
+           fprintf(NetTrace, "TERMINAL-TYPE ");
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+               break;
+           case TELQUAL_SEND:
+               fprintf(NetTrace, "SEND");
+               break;
+           default:
+               fprintf(NetTrace,
+                               "- unknown qualifier %d (0x%x).",
+                               pointer[1], pointer[1]);
+           }
+           break;
+       case TELOPT_TSPEED:
+           fprintf(NetTrace, "TERMINAL-SPEED");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               fprintf(NetTrace, " IS ");
+               fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
+               break;
+           default:
+               if (pointer[1] == 1)
+                   fprintf(NetTrace, " SEND");
+               else
+                   fprintf(NetTrace, " %d (unknown)", pointer[1]);
+               for (i = 2; i < length; i++)
+                   fprintf(NetTrace, " ?%d?", pointer[i]);
+               break;
+           }
+           break;
+
+       case TELOPT_LFLOW:
+           fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
+           switch (pointer[1]) {
+           case LFLOW_OFF:
+               fprintf(NetTrace, " OFF"); break;
+           case LFLOW_ON:
+               fprintf(NetTrace, " ON"); break;
+           case LFLOW_RESTART_ANY:
+               fprintf(NetTrace, " RESTART-ANY"); break;
+           case LFLOW_RESTART_XON:
+               fprintf(NetTrace, " RESTART-XON"); break;
+           default:
+               fprintf(NetTrace, " %d (unknown)", pointer[1]);
+           }
+           for (i = 2; i < length; i++)
+               fprintf(NetTrace, " ?%d?", pointer[i]);
+           break;
+
+       case TELOPT_NAWS:
+           fprintf(NetTrace, "NAWS");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
+           if (length == 2) {
+               fprintf(NetTrace, " ?%d?", pointer[1]);
+               break;
+           }
+           fprintf(NetTrace, " %d %d (%d)",
+               pointer[1], pointer[2],
+               (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
+           if (length == 4) {
+               fprintf(NetTrace, " ?%d?", pointer[3]);
+               break;
+           }
+           fprintf(NetTrace, " %d %d (%d)",
+               pointer[3], pointer[4],
+               (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
+           for (i = 5; i < length; i++)
+               fprintf(NetTrace, " ?%d?", pointer[i]);
+           break;
+
+#if    defined(AUTHENTICATION)
+       case TELOPT_AUTHENTICATION:
+           fprintf(NetTrace, "AUTHENTICATION");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
+           switch (pointer[1]) {
+           case TELQUAL_REPLY:
+           case TELQUAL_IS:
+               fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
+                                                       "IS" : "REPLY");
+               if (AUTHTYPE_NAME_OK(pointer[2]))
+                   fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
+               else
+                   fprintf(NetTrace, "%d ", pointer[2]);
+               if (length < 3) {
+                   fprintf(NetTrace, "(partial suboption??\?)");
+                   break;
+               }
+               fprintf(NetTrace, "%s|%s",
+                       ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+                       "CLIENT" : "SERVER",
+                       ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+                       "MUTUAL" : "ONE-WAY");
+
+               auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+               fprintf(NetTrace, "%s", buf);
+               break;
+
+           case TELQUAL_SEND:
+               i = 2;
+               fprintf(NetTrace, " SEND ");
+               while (i < length) {
+                   if (AUTHTYPE_NAME_OK(pointer[i]))
+                       fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
+                   else
+                       fprintf(NetTrace, "%d ", pointer[i]);
+                   if (++i >= length) {
+                       fprintf(NetTrace, "(partial suboption??\?)");
+                       break;
+                   }
+                   fprintf(NetTrace, "%s|%s ",
+                       ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+                                                       "CLIENT" : "SERVER",
+                       ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+                                                       "MUTUAL" : "ONE-WAY");
+                   ++i;
+               }
+               break;
+
+           case TELQUAL_NAME:
+               i = 2;
+               fprintf(NetTrace, " NAME \"");
+               while (i < length)
+                   putc(pointer[i++], NetTrace);
+               putc('"', NetTrace);
+               break;
+
+           default:
+                   for (i = 2; i < length; i++)
+                       fprintf(NetTrace, " ?%d?", pointer[i]);
+                   break;
+           }
+           break;
+#endif
+
+#ifdef ENCRYPTION
+       case TELOPT_ENCRYPT:
+           fprintf(NetTrace, "ENCRYPT");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
+           switch (pointer[1]) {
+           case ENCRYPT_START:
+               fprintf(NetTrace, " START");
+               break;
+
+           case ENCRYPT_END:
+               fprintf(NetTrace, " END");
+               break;
+
+           case ENCRYPT_REQSTART:
+               fprintf(NetTrace, " REQUEST-START");
+               break;
+
+           case ENCRYPT_REQEND:
+               fprintf(NetTrace, " REQUEST-END");
+               break;
+
+           case ENCRYPT_IS:
+           case ENCRYPT_REPLY:
+               fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
+                                                       "IS" : "REPLY");
+               if (length < 3) {
+                   fprintf(NetTrace, " (partial suboption??\?)");
+                   break;
+               }
+               if (ENCTYPE_NAME_OK(pointer[2]))
+                   fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
+               else
+                   fprintf(NetTrace, " %d (unknown)", pointer[2]);
+
+               encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+               fprintf(NetTrace, "%s", buf);
+               break;
+
+           case ENCRYPT_SUPPORT:
+               i = 2;
+               fprintf(NetTrace, " SUPPORT ");
+               while (i < length) {
+                   if (ENCTYPE_NAME_OK(pointer[i]))
+                       fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
+                   else
+                       fprintf(NetTrace, "%d ", pointer[i]);
+                   i++;
+               }
+               break;
+
+           case ENCRYPT_ENC_KEYID:
+               fprintf(NetTrace, " ENC_KEYID ");
+               goto encommon;
+
+           case ENCRYPT_DEC_KEYID:
+               fprintf(NetTrace, " DEC_KEYID ");
+               goto encommon;
+
+           default:
+               fprintf(NetTrace, " %d (unknown)", pointer[1]);
+           encommon:
+               for (i = 2; i < length; i++)
+                   fprintf(NetTrace, " %d", pointer[i]);
+               break;
+           }
+           break;
+#endif /* ENCRYPTION */
+
+       case TELOPT_LINEMODE:
+           fprintf(NetTrace, "LINEMODE ");
+           if (length < 2) {
+               fprintf(NetTrace, " (empty suboption??\?)");
+               break;
+           }
+           switch (pointer[1]) {
+           case WILL:
+               fprintf(NetTrace, "WILL ");
+               goto common;
+           case WONT:
+               fprintf(NetTrace, "WONT ");
+               goto common;
+           case DO:
+               fprintf(NetTrace, "DO ");
+               goto common;
+           case DONT:
+               fprintf(NetTrace, "DONT ");
+           common:
+               if (length < 3) {
+                   fprintf(NetTrace, "(no option??\?)");
+                   break;
+               }
+               switch (pointer[2]) {
+               case LM_FORWARDMASK:
+                   fprintf(NetTrace, "Forward Mask");
+                   for (i = 3; i < length; i++)
+                       fprintf(NetTrace, " %x", pointer[i]);
+                   break;
+               default:
+                   fprintf(NetTrace, "%d (unknown)", pointer[2]);
+                   for (i = 3; i < length; i++)
+                       fprintf(NetTrace, " %d", pointer[i]);
+                   break;
+               }
+               break;
+
+           case LM_SLC:
+               fprintf(NetTrace, "SLC");
+               for (i = 2; i < length - 2; i += 3) {
+                   if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
+                       fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
+                   else
+                       fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
+                   switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
+                   case SLC_NOSUPPORT:
+                       fprintf(NetTrace, " NOSUPPORT"); break;
+                   case SLC_CANTCHANGE:
+                       fprintf(NetTrace, " CANTCHANGE"); break;
+                   case SLC_VARIABLE:
+                       fprintf(NetTrace, " VARIABLE"); break;
+                   case SLC_DEFAULT:
+                       fprintf(NetTrace, " DEFAULT"); break;
+                   }
+                   fprintf(NetTrace, "%s%s%s",
+                       pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
+                       pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
+                       pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
+                   if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
+                                               SLC_FLUSHOUT| SLC_LEVELBITS))
+                       fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
+                   fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
+                   if ((pointer[i+SLC_VALUE] == IAC) &&
+                       (pointer[i+SLC_VALUE+1] == IAC))
+                               i++;
+               }
+               for (; i < length; i++)
+                   fprintf(NetTrace, " ?%d?", pointer[i]);
+               break;
+
+           case LM_MODE:
+               fprintf(NetTrace, "MODE ");
+               if (length < 3) {
+                   fprintf(NetTrace, "(no mode??\?)");
+                   break;
+               }
+               {
+                   char tbuf[64];
+                   sprintf(tbuf, "%s%s%s%s%s",
+                       pointer[2]&MODE_EDIT ? "|EDIT" : "",
+                       pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
+                       pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
+                       pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
+                       pointer[2]&MODE_ACK ? "|ACK" : "");
+                   fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
+               }
+               if (pointer[2]&~(MODE_MASK))
+                   fprintf(NetTrace, " (0x%x)", pointer[2]);
+               for (i = 3; i < length; i++)
+                   fprintf(NetTrace, " ?0x%x?", pointer[i]);
+               break;
+           default:
+               fprintf(NetTrace, "%d (unknown)", pointer[1]);
+               for (i = 2; i < length; i++)
+                   fprintf(NetTrace, " %d", pointer[i]);
+           }
+           break;
+
+       case TELOPT_STATUS: {
+           register char *cp;
+           register int j, k;
+
+           fprintf(NetTrace, "STATUS");
+
+           switch (pointer[1]) {
+           default:
+               if (pointer[1] == TELQUAL_SEND)
+                   fprintf(NetTrace, " SEND");
+               else
+                   fprintf(NetTrace, " %d (unknown)", pointer[1]);
+               for (i = 2; i < length; i++)
+                   fprintf(NetTrace, " ?%d?", pointer[i]);
+               break;
+           case TELQUAL_IS:
+               if (--want_status_response < 0)
+                   want_status_response = 0;
+               if (NetTrace == stdout)
+                   fprintf(NetTrace, " IS\r\n");
+               else
+                   fprintf(NetTrace, " IS\n");
+
+               for (i = 2; i < length; i++) {
+                   switch(pointer[i]) {
+                   case DO:    cp = "DO"; goto common2;
+                   case DONT:  cp = "DONT"; goto common2;
+                   case WILL:  cp = "WILL"; goto common2;
+                   case WONT:  cp = "WONT"; goto common2;
+                   common2:
+                       i++;
+                       if (TELOPT_OK((int)pointer[i]))
+                           fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
+                       else
+                           fprintf(NetTrace, " %s %d", cp, pointer[i]);
+
+                       if (NetTrace == stdout)
+                           fprintf(NetTrace, "\r\n");
+                       else
+                           fprintf(NetTrace, "\n");
+                       break;
+
+                   case SB:
+                       fprintf(NetTrace, " SB ");
+                       i++;
+                       j = k = i;
+                       while (j < length) {
+                           if (pointer[j] == SE) {
+                               if (j+1 == length)
+                                   break;
+                               if (pointer[j+1] == SE)
+                                   j++;
+                               else
+                                   break;
+                           }
+                           pointer[k++] = pointer[j++];
+                       }
+                       printsub(0, &pointer[i], k - i);
+                       if (i < length) {
+                           fprintf(NetTrace, " SE");
+                           i = j;
+                       } else
+                           i = j - 1;
+
+                       if (NetTrace == stdout)
+                           fprintf(NetTrace, "\r\n");
+                       else
+                           fprintf(NetTrace, "\n");
+
+                       break;
+
+                   default:
+                       fprintf(NetTrace, " %d", pointer[i]);
+                       break;
+                   }
+               }
+               break;
+           }
+           break;
+         }
+
+       case TELOPT_XDISPLOC:
+           fprintf(NetTrace, "X-DISPLAY-LOCATION ");
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+               break;
+           case TELQUAL_SEND:
+               fprintf(NetTrace, "SEND");
+               break;
+           default:
+               fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
+                               pointer[1], pointer[1]);
+           }
+           break;
+
+       case TELOPT_NEW_ENVIRON:
+           fprintf(NetTrace, "NEW-ENVIRON ");
+#ifdef OLD_ENVIRON
+           goto env_common1;
+       case TELOPT_OLD_ENVIRON:
+           fprintf(NetTrace, "OLD-ENVIRON");
+       env_common1:
+#endif
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               fprintf(NetTrace, "IS ");
+               goto env_common;
+           case TELQUAL_SEND:
+               fprintf(NetTrace, "SEND ");
+               goto env_common;
+           case TELQUAL_INFO:
+               fprintf(NetTrace, "INFO ");
+           env_common:
+               {
+                   register int noquote = 2;
+#if defined(ENV_HACK) && defined(OLD_ENVIRON)
+                   extern int old_env_var, old_env_value;
+#endif
+                   for (i = 2; i < length; i++ ) {
+                       switch (pointer[i]) {
+                       case NEW_ENV_VALUE:
+#ifdef OLD_ENVIRON
+                    /* case NEW_ENV_OVAR: */
+                           if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef        ENV_HACK
+                               if (old_env_var == OLD_ENV_VALUE)
+                                   fprintf(NetTrace, "\" (VALUE) " + noquote);
+                               else
+# endif
+                                   fprintf(NetTrace, "\" VAR " + noquote);
+                           } else
+#endif /* OLD_ENVIRON */
+                               fprintf(NetTrace, "\" VALUE " + noquote);
+                           noquote = 2;
+                           break;
+
+                       case NEW_ENV_VAR:
+#ifdef OLD_ENVIRON
+                    /* case OLD_ENV_VALUE: */
+                           if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef        ENV_HACK
+                               if (old_env_value == OLD_ENV_VAR)
+                                   fprintf(NetTrace, "\" (VAR) " + noquote);
+                               else
+# endif
+                                   fprintf(NetTrace, "\" VALUE " + noquote);
+                           } else
+#endif /* OLD_ENVIRON */
+                               fprintf(NetTrace, "\" VAR " + noquote);
+                           noquote = 2;
+                           break;
+
+                       case ENV_ESC:
+                           fprintf(NetTrace, "\" ESC " + noquote);
+                           noquote = 2;
+                           break;
+
+                       case ENV_USERVAR:
+                           fprintf(NetTrace, "\" USERVAR " + noquote);
+                           noquote = 2;
+                           break;
+
+                       default:
+                       def_case:
+                           if (isprint(pointer[i]) && pointer[i] != '"') {
+                               if (noquote) {
+                                   putc('"', NetTrace);
+                                   noquote = 0;
+                               }
+                               putc(pointer[i], NetTrace);
+                           } else {
+                               fprintf(NetTrace, "\" %03o " + noquote,
+                                                       pointer[i]);
+                               noquote = 2;
+                           }
+                           break;
+                       }
+                   }
+                   if (!noquote)
+                       putc('"', NetTrace);
+                   break;
+               }
+           }
+           break;
+
+       default:
+           if (TELOPT_OK(pointer[0]))
+               fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
+           else
+               fprintf(NetTrace, "%d (unknown)", pointer[0]);
+           for (i = 1; i < length; i++)
+               fprintf(NetTrace, " %d", pointer[i]);
+           break;
+       }
+       if (direction) {
+           if (NetTrace == stdout)
+               fprintf(NetTrace, "\r\n");
+           else
+               fprintf(NetTrace, "\n");
+       }
+       if (NetTrace == stdout)
+           fflush(NetTrace);
+    }
+}
+
+/* EmptyTerminal - called to make sure that the terminal buffer is empty.
+ *                     Note that we consider the buffer to run all the
+ *                     way to the kernel (thus the select).
+ */
+
+    void
+EmptyTerminal()
+{
+#if    defined(unix) || defined(__APPLE__)
+    fd_set     o;
+
+    FD_ZERO(&o);
+#endif /* defined(unix) || defined(__APPLE__) */
+
+    if (TTYBYTES() == 0) {
+#if    defined(unix) || defined(__APPLE__)
+       FD_SET(tout, &o);
+       (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
+                       (struct timeval *) 0);  /* wait for TTLOWAT */
+#endif /* defined(unix) || defined(__APPLE__) */
+    } else {
+       while (TTYBYTES()) {
+           (void) ttyflush(0);
+#if    defined(unix) || defined(__APPLE__)
+           FD_SET(tout, &o);
+           (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
+                               (struct timeval *) 0);  /* wait for TTLOWAT */
+#endif /* defined(unix) || defined(__APPLE__) */
+       }
+    }
+}
+
+    void
+SetForExit()
+{
+    setconnmode(0);
+#if    defined(TN3270)
+    if (In3270) {
+       Finish3270();
+    }
+#else  /* defined(TN3270) */
+    do {
+       (void)telrcv();                 /* Process any incoming data */
+       EmptyTerminal();
+    } while (ring_full_count(&netiring));      /* While there is any */
+#endif /* defined(TN3270) */
+    setcommandmode();
+    fflush(stdout);
+    fflush(stderr);
+#if    defined(TN3270)
+    if (In3270) {
+       StopScreen(1);
+    }
+#endif /* defined(TN3270) */
+    setconnmode(0);
+    EmptyTerminal();                   /* Flush the path to the tty */
+    setcommandmode();
+}
+
+    void
+Exit(returnCode)
+    int returnCode;
+{
+    SetForExit();
+    exit(returnCode);
+}
+
+    void
+ExitString(string, returnCode)
+    char *string;
+    int returnCode;
+{
+    SetForExit();
+    fwrite(string, 1, strlen(string), stderr);
+    exit(returnCode);
+}
diff --git a/telnetd.tproj/Makefile b/telnetd.tproj/Makefile
new file mode 100644 (file)
index 0000000..63a671f
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = telnetd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = defs.h ext.h pathnames.h telnetd.h
+
+CFILES = authenc.c global.c slc.c state.c sys_term.c telnetd.c\
+         termstat.c utility.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble telnetd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION
+WINDOWS_PB_CFLAGS = -DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION
+PDO_UNIX_PB_CFLAGS = -DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/telnetd.tproj/Makefile.postamble b/telnetd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7ede358
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
diff --git a/telnetd.tproj/Makefile.preamble b/telnetd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..70aa1d8
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = -ltelnet
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
diff --git a/telnetd.tproj/PB.project b/telnetd.tproj/PB.project
new file mode 100644 (file)
index 0000000..8dfbe1c
--- /dev/null
@@ -0,0 +1,50 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (defs.h, ext.h, pathnames.h, telnetd.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (
+            authenc.c, 
+            global.c, 
+            slc.c, 
+            state.c, 
+            sys_term.c, 
+            telnetd.c, 
+            termstat.c, 
+            utility.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, telnetd.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION"; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION"; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = telnetd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = "-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION"; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/telnetd.tproj/authenc.c b/telnetd.tproj/authenc.c
new file mode 100644 (file)
index 0000000..7891835
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)authenc.c  8.2 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#if    defined(AUTHENTICATION) || defined(ENCRYPTION)
+#include "telnetd.h"
+#include <libtelnet/misc.h>
+
+       int
+net_write(str, len)
+       unsigned char *str;
+       int len;
+{
+       if (nfrontp + len < netobuf + BUFSIZ) {
+               memmove((void *)nfrontp, (void *)str, len);
+               nfrontp += len;
+               return(len);
+       }
+       return(0);
+}
+
+       void
+net_encrypt()
+{
+#ifdef ENCRYPTION
+       char *s = (nclearto > nbackp) ? nclearto : nbackp;
+       if (s < nfrontp && encrypt_output) {
+               (*encrypt_output)((unsigned char *)s, nfrontp - s);
+       }
+       nclearto = nfrontp;
+#endif /* ENCRYPTION */
+}
+
+       int
+telnet_spin()
+{
+       ttloop();
+       return(0);
+}
+
+       char *
+telnet_getenv(val)
+       char *val;
+{
+       extern char *getenv();
+       return(getenv(val));
+}
+
+       char *
+telnet_gets(prompt, result, length, echo)
+       char *prompt;
+       char *result;
+       int length;
+       int echo;
+{
+       return((char *)0);
+}
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
diff --git a/telnetd.tproj/defs.h b/telnetd.tproj/defs.h
new file mode 100644 (file)
index 0000000..1224895
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)defs.h      8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Telnet server defines
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifndef        BSD
+# define       BSD 43
+#endif
+
+#if    defined(CRAY) && !defined(LINEMODE)
+# define SYSV_TERMIO
+# define LINEMODE
+# define KLUDGELINEMODE
+# define DIAGNOSTICS
+# if defined(UNICOS50) && !defined(UNICOS5)
+#  define UNICOS5
+# endif
+# if !defined(UNICOS5)
+#  define BFTPDAEMON
+#  define HAS_IP_TOS
+# endif
+#endif /* CRAY */
+#if defined(UNICOS5) && !defined(NO_SETSID)
+# define NO_SETSID
+#endif
+
+#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS)
+#define TELOPTS
+#define TELCMDS
+#define        SLC_NAMES
+#endif
+
+#if    defined(SYSV_TERMIO) && !defined(USE_TERMIO)
+# define       USE_TERMIO
+#endif
+
+#include <sys/socket.h>
+#ifndef        CRAY
+#include <sys/wait.h>
+#endif /* CRAY */
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#ifndef        FILIO_H
+#include <sys/ioctl.h>
+#else
+#include <sys/filio.h>
+#endif
+
+#include <netinet/in.h>
+
+#include <arpa/telnet.h>
+
+#include <stdio.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include <signal.h>
+#include <errno.h>
+#include <netdb.h>
+#include <syslog.h>
+#ifndef        LOG_DAEMON
+#define        LOG_DAEMON      0
+#endif
+#ifndef        LOG_ODELAY
+#define        LOG_ODELAY      0
+#endif
+#include <ctype.h>
+#ifndef NO_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#ifndef        USE_TERMIO
+#include <sgtty.h>
+#else
+# ifdef        SYSV_TERMIO
+# include <termio.h>
+# else
+#  ifdef __APPLE__
+#   include <sys/termios.h>
+#  else
+#   include <termios.h>
+#  endif
+# endif
+#endif
+#if !defined(USE_TERMIO) || defined(NO_CC_T)
+typedef unsigned char cc_t;
+#endif
+
+#ifdef __STDC__
+#include <unistd.h>
+#endif
+
+#ifndef _POSIX_VDISABLE
+# ifdef VDISABLE
+#  define _POSIX_VDISABLE VDISABLE
+# else
+#  define _POSIX_VDISABLE ((unsigned char)'\377')
+# endif
+#endif
+
+
+#ifdef CRAY
+# ifdef        CRAY1
+# include <sys/pty.h>
+#  ifndef FD_ZERO
+# include <sys/select.h>
+#  endif /* FD_ZERO */
+# endif        /* CRAY1 */
+
+#include <memory.h>
+#endif /* CRAY */
+
+#ifdef __hpux
+#include <sys/ptyio.h>
+#endif
+
+#if    !defined(TIOCSCTTY) && defined(TCSETCTTY)
+# define       TIOCSCTTY TCSETCTTY
+#endif
+
+#ifndef        FD_SET
+#ifndef        HAVE_fd_set
+typedef struct fd_set { int fds_bits[1]; } fd_set;
+#endif
+
+#define        FD_SET(n, p)    ((p)->fds_bits[0] |= (1<<(n)))
+#define        FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1<<(n)))
+#define        FD_ISSET(n, p)  ((p)->fds_bits[0] & (1<<(n)))
+#define FD_ZERO(p)     ((p)->fds_bits[0] = 0)
+#endif /* FD_SET */
+
+/*
+ * I/O data buffers defines
+ */
+#define        NETSLOP 64
+#ifdef CRAY
+#undef BUFSIZ
+#define BUFSIZ  2048
+#endif
+
+#define        NIACCUM(c)      {   *netip++ = c; \
+                           ncc++; \
+                       }
+
+/* clock manipulations */
+#define        settimer(x)     (clocks.x = ++clocks.system)
+#define        sequenceIs(x,y) (clocks.x < clocks.y)
+
+/*
+ * Linemode support states, in decreasing order of importance
+ */
+#define REAL_LINEMODE  0x04
+#define KLUDGE_OK      0x03
+#define        NO_AUTOKLUDGE   0x02
+#define KLUDGE_LINEMODE        0x01
+#define NO_LINEMODE    0x00
+
+/*
+ * Structures of information for each special character function.
+ */
+typedef struct {
+       unsigned char   flag;           /* the flags for this function */
+       cc_t            val;            /* the value of the special character */
+} slcent, *Slcent;
+
+typedef struct {
+       slcent          defset;         /* the default settings */
+       slcent          current;        /* the current settings */
+       cc_t            *sptr;          /* a pointer to the char in */
+                                       /* system data structures */
+} slcfun, *Slcfun;
+
+#ifdef DIAGNOSTICS
+/*
+ * Diagnostics capabilities
+ */
+#define        TD_REPORT       0x01    /* Report operations to client */
+#define TD_EXERCISE    0x02    /* Exercise client's implementation */
+#define TD_NETDATA     0x04    /* Display received data stream */
+#define TD_PTYDATA     0x08    /* Display data passed to pty */
+#define        TD_OPTIONS      0x10    /* Report just telnet options */
+#endif /* DIAGNOSTICS */
+
+/*
+ * We keep track of each side of the option negotiation.
+ */
+
+#define        MY_STATE_WILL           0x01
+#define        MY_WANT_STATE_WILL      0x02
+#define        MY_STATE_DO             0x04
+#define        MY_WANT_STATE_DO        0x08
+
+/*
+ * Macros to check the current state of things
+ */
+
+#define        my_state_is_do(opt)             (options[opt]&MY_STATE_DO)
+#define        my_state_is_will(opt)           (options[opt]&MY_STATE_WILL)
+#define my_want_state_is_do(opt)       (options[opt]&MY_WANT_STATE_DO)
+#define my_want_state_is_will(opt)     (options[opt]&MY_WANT_STATE_WILL)
+
+#define        my_state_is_dont(opt)           (!my_state_is_do(opt))
+#define        my_state_is_wont(opt)           (!my_state_is_will(opt))
+#define my_want_state_is_dont(opt)     (!my_want_state_is_do(opt))
+#define my_want_state_is_wont(opt)     (!my_want_state_is_will(opt))
+
+#define        set_my_state_do(opt)            (options[opt] |= MY_STATE_DO)
+#define        set_my_state_will(opt)          (options[opt] |= MY_STATE_WILL)
+#define        set_my_want_state_do(opt)       (options[opt] |= MY_WANT_STATE_DO)
+#define        set_my_want_state_will(opt)     (options[opt] |= MY_WANT_STATE_WILL)
+
+#define        set_my_state_dont(opt)          (options[opt] &= ~MY_STATE_DO)
+#define        set_my_state_wont(opt)          (options[opt] &= ~MY_STATE_WILL)
+#define        set_my_want_state_dont(opt)     (options[opt] &= ~MY_WANT_STATE_DO)
+#define        set_my_want_state_wont(opt)     (options[opt] &= ~MY_WANT_STATE_WILL)
+
+/*
+ * Tricky code here.  What we want to know is if the MY_STATE_WILL
+ * and MY_WANT_STATE_WILL bits have the same value.  Since the two
+ * bits are adjacent, a little arithmatic will show that by adding
+ * in the lower bit, the upper bit will be set if the two bits were
+ * different, and clear if they were the same.
+ */
+#define my_will_wont_is_changing(opt) \
+                       ((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL)
+
+#define my_do_dont_is_changing(opt) \
+                       ((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO)
+
+/*
+ * Make everything symetrical
+ */
+
+#define        HIS_STATE_WILL                  MY_STATE_DO
+#define        HIS_WANT_STATE_WILL             MY_WANT_STATE_DO
+#define HIS_STATE_DO                   MY_STATE_WILL
+#define HIS_WANT_STATE_DO              MY_WANT_STATE_WILL
+
+#define        his_state_is_do                 my_state_is_will
+#define        his_state_is_will               my_state_is_do
+#define his_want_state_is_do           my_want_state_is_will
+#define his_want_state_is_will         my_want_state_is_do
+
+#define        his_state_is_dont               my_state_is_wont
+#define        his_state_is_wont               my_state_is_dont
+#define his_want_state_is_dont         my_want_state_is_wont
+#define his_want_state_is_wont         my_want_state_is_dont
+
+#define        set_his_state_do                set_my_state_will
+#define        set_his_state_will              set_my_state_do
+#define        set_his_want_state_do           set_my_want_state_will
+#define        set_his_want_state_will         set_my_want_state_do
+
+#define        set_his_state_dont              set_my_state_wont
+#define        set_his_state_wont              set_my_state_dont
+#define        set_his_want_state_dont         set_my_want_state_wont
+#define        set_his_want_state_wont         set_my_want_state_dont
+
+#define his_will_wont_is_changing      my_do_dont_is_changing
+#define his_do_dont_is_changing                my_will_wont_is_changing
diff --git a/telnetd.tproj/ext.h b/telnetd.tproj/ext.h
new file mode 100644 (file)
index 0000000..18ab636
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ext.h       8.2 (Berkeley) 12/15/93
+ */
+
+/*
+ * Telnet server variable declarations
+ */
+extern char    options[256];
+extern char    do_dont_resp[256];
+extern char    will_wont_resp[256];
+extern int     linemode;       /* linemode on/off */
+#ifdef LINEMODE
+extern int     uselinemode;    /* what linemode to use (on/off) */
+extern int     editmode;       /* edit modes in use */
+extern int     useeditmode;    /* edit modes to use */
+extern int     alwayslinemode; /* command line option */
+# ifdef        KLUDGELINEMODE
+extern int     lmodetype;      /* Client support for linemode */
+# endif        /* KLUDGELINEMODE */
+#endif /* LINEMODE */
+extern int     flowmode;       /* current flow control state */
+extern int     restartany;     /* restart output on any character state */
+#ifdef DIAGNOSTICS
+extern int     diagnostic;     /* telnet diagnostic capabilities */
+#endif /* DIAGNOSTICS */
+#ifdef BFTPDAEMON
+extern int     bftpd;          /* behave as bftp daemon */
+#endif /* BFTPDAEMON */
+#if    defined(SecurID)
+extern int     require_SecurID;
+#endif
+#if    defined(AUTHENTICATION)
+extern int     auth_level;
+#endif
+
+extern slcfun  slctab[NSLC + 1];       /* slc mapping table */
+
+extern char    *terminaltype;
+
+/*
+ * I/O data buffers, pointers, and counters.
+ */
+extern char    ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
+
+extern char    netibuf[BUFSIZ], *netip;
+
+extern char    netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
+extern char    *neturg;                /* one past last bye of urgent data */
+
+extern int     pcc, ncc;
+
+#if defined(CRAY2) && defined(UNICOS5)
+extern int unpcc;  /* characters left unprocessed by CRAY-2 terminal routine */
+extern char *unptyip;  /* pointer to remaining characters in buffer */
+#endif
+
+extern int     pty, net;
+#ifdef __APPLE__
+extern char    line[16];
+#else
+extern char    *line;
+#endif /* !NeXT */
+extern int     SYNCHing;               /* we are in TELNET SYNCH mode */
+
+#ifndef        P
+# ifdef        __STDC__
+#  define P(x) x
+# else
+#  define P(x) ()
+# endif
+#endif
+
+extern void
+       _termstat P((void)),
+       add_slc P((int, int, int)),
+       check_slc P((void)),
+       change_slc P((int, int, int)),
+       cleanup P((int)),
+       clientstat P((int, int, int)),
+       copy_termbuf P((char *, int)),
+       deferslc P((void)),
+       defer_terminit P((void)),
+       do_opt_slc P((unsigned char *, int)),
+       doeof P((void)),
+       dooption P((int)),
+       dontoption P((int)),
+       edithost P((char *, char *)),
+       fatal P((int, char *)),
+       fatalperror P((int, char *)),
+       get_slc_defaults P((void)),
+       init_env P((void)),
+       init_termbuf P((void)),
+       interrupt P((void)),
+       localstat P((void)),
+       flowstat P((void)),
+       netclear P((void)),
+       netflush P((void)),
+#ifdef DIAGNOSTICS
+       printoption P((char *, int)),
+       printdata P((char *, char *, int)),
+       printsub P((int, unsigned char *, int)),
+#endif
+       ptyflush P((void)),
+       putchr P((int)),
+       putf P((char *, char *)),
+       recv_ayt P((void)),
+       send_do P((int, int)),
+       send_dont P((int, int)),
+       send_slc P((void)),
+       send_status P((void)),
+       send_will P((int, int)),
+       send_wont P((int, int)),
+       sendbrk P((void)),
+       sendsusp P((void)),
+       set_termbuf P((void)),
+       start_login P((char *, int, char *)),
+       start_slc P((int)),
+#if    defined(AUTHENTICATION)
+       start_slave P((char *)),
+#else
+       start_slave P((char *, int, char *)),
+#endif
+       suboption P((void)),
+       telrcv P((void)),
+       ttloop P((void)),
+       tty_binaryin P((int)),
+       tty_binaryout P((int));
+
+extern int
+       end_slc P((unsigned char **)),
+       getnpty P((void)),
+#ifndef convex
+       getpty P((int *)),
+#endif
+       login_tty P((int)),
+       spcset P((int, cc_t *, cc_t **)),
+       stilloob P((int)),
+       terminit P((void)),
+       termstat P((void)),
+       tty_flowmode P((void)),
+       tty_restartany P((void)),
+       tty_isbinaryin P((void)),
+       tty_isbinaryout P((void)),
+       tty_iscrnl P((void)),
+       tty_isecho P((void)),
+       tty_isediting P((void)),
+       tty_islitecho P((void)),
+       tty_isnewmap P((void)),
+       tty_israw P((void)),
+       tty_issofttab P((void)),
+       tty_istrapsig P((void)),
+       tty_linemode P((void));
+
+extern void
+       tty_rspeed P((int)),
+       tty_setecho P((int)),
+       tty_setedit P((int)),
+       tty_setlinemode P((int)),
+       tty_setlitecho P((int)),
+       tty_setsig P((int)),
+       tty_setsofttab P((int)),
+       tty_tspeed P((int)),
+       willoption P((int)),
+       wontoption P((int)),
+       writenet P((unsigned char *, int));
+
+#ifdef ENCRYPTION
+extern void    (*encrypt_output) P((unsigned char *, int));
+extern int     (*decrypt_input) P((int));
+extern char    *nclearto;
+#endif /* ENCRYPTION */
+
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+extern struct {
+    int
+       system,                 /* what the current time is */
+       echotoggle,             /* last time user entered echo character */
+       modenegotiated,         /* last time operating mode negotiated */
+       didnetreceive,          /* last time we read data from network */
+       ttypesubopt,            /* ttype subopt is received */
+       tspeedsubopt,           /* tspeed subopt is received */
+       environsubopt,          /* environ subopt is received */
+       oenvironsubopt,         /* old environ subopt is received */
+       xdisplocsubopt,         /* xdisploc subopt is received */
+       baseline,               /* time started to do timed action */
+       gotDM;                  /* when did we last see a data mark */
+} clocks;
+
+
+#if    defined(CRAY2) && defined(UNICOS5)
+extern int     needtermstat;
+#endif
+
+#ifndef        DEFAULT_IM
+# ifdef CRAY
+#  define DEFAULT_IM   "\r\n\r\nCray UNICOS (%h) (%t)\r\n\r\r\n\r"
+# else
+#  ifdef sun
+#   define DEFAULT_IM  "\r\n\r\nSunOS UNIX (%h) (%t)\r\n\r\r\n\r"
+#  else
+#   ifdef ultrix
+#    define DEFAULT_IM "\r\n\r\nULTRIX (%h) (%t)\r\n\r\r\n\r"
+#   else
+#    define DEFAULT_IM "\r\n\r\n4.4 BSD (%h) (%t)\r\n\r\r\n\r"
+#   endif
+#  endif
+# endif
+#endif
diff --git a/telnetd.tproj/global.c b/telnetd.tproj/global.c
new file mode 100644 (file)
index 0000000..ebed4ed
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)global.c   8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * Allocate global variables.  We do this
+ * by including the header file that defines
+ * them all as externs, but first we define
+ * the keyword "extern" to be nothing, so that
+ * we will actually allocate the space.
+ */
+
+#include "defs.h"
+#define extern
+#include "ext.h"
diff --git a/telnetd.tproj/pathnames.h b/telnetd.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..c9ac41f
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ */
+
+#if BSD > 43
+
+# include <paths.h>
+
+# ifndef _PATH_LOGIN
+#  define      _PATH_LOGIN     "/usr/bin/login"
+# endif
+
+#else
+# define       _PATH_TTY       "/dev/tty"
+# ifndef _PATH_LOGIN
+#  define      _PATH_LOGIN     "/bin/login"
+# endif
+
+#endif
+
+#ifdef BFTPDAEMON
+#define                BFTPPATH        "/usr/ucb/bftp"
+#endif  /* BFTPDAEMON */
diff --git a/telnetd.tproj/slc.c b/telnetd.tproj/slc.c
new file mode 100644 (file)
index 0000000..a7b280d
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)slc.c      8.2 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include "telnetd.h"
+
+#ifdef LINEMODE
+/*
+ * local varibles
+ */
+static unsigned char   *def_slcbuf = (unsigned char *)0;
+static int             def_slclen = 0;
+static int             slcchange;      /* change to slc is requested */
+static unsigned char   *slcptr;        /* pointer into slc buffer */
+static unsigned char   slcbuf[NSLC*6]; /* buffer for slc negotiation */
+
+/*
+ * send_slc
+ *
+ * Write out the current special characters to the client.
+ */
+       void
+send_slc()
+{
+       register int i;
+
+       /*
+        * Send out list of triplets of special characters
+        * to client.  We only send info on the characters
+        * that are currently supported.
+        */
+       for (i = 1; i <= NSLC; i++) {
+               if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT)
+                       continue;
+               add_slc((unsigned char)i, slctab[i].current.flag,
+                                                       slctab[i].current.val);
+       }
+
+}  /* end of send_slc */
+
+/*
+ * default_slc
+ *
+ * Set pty special characters to all the defaults.
+ */
+       void
+default_slc()
+{
+       register int i;
+
+       for (i = 1; i <= NSLC; i++) {
+               slctab[i].current.val = slctab[i].defset.val;
+               if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE))
+                       slctab[i].current.flag = SLC_NOSUPPORT;
+               else
+                       slctab[i].current.flag = slctab[i].defset.flag;
+               if (slctab[i].sptr) {
+                       *(slctab[i].sptr) = slctab[i].defset.val;
+               }
+       }
+       slcchange = 1;
+
+}  /* end of default_slc */
+#endif /* LINEMODE */
+
+/*
+ * get_slc_defaults
+ *
+ * Initialize the slc mapping table.
+ */
+       void
+get_slc_defaults()
+{
+       register int i;
+
+       init_termbuf();
+
+       for (i = 1; i <= NSLC; i++) {
+               slctab[i].defset.flag =
+                       spcset(i, &slctab[i].defset.val, &slctab[i].sptr);
+               slctab[i].current.flag = SLC_NOSUPPORT;
+               slctab[i].current.val = 0;
+       }
+
+}  /* end of get_slc_defaults */
+
+#ifdef LINEMODE
+/*
+ * add_slc
+ *
+ * Add an slc triplet to the slc buffer.
+ */
+       void
+add_slc(func, flag, val)
+       register char func, flag;
+       register cc_t val;
+{
+
+       if ((*slcptr++ = (unsigned char)func) == 0xff)
+               *slcptr++ = 0xff;
+
+       if ((*slcptr++ = (unsigned char)flag) == 0xff)
+               *slcptr++ = 0xff;
+
+       if ((*slcptr++ = (unsigned char)val) == 0xff)
+               *slcptr++ = 0xff;
+
+}  /* end of add_slc */
+
+/*
+ * start_slc
+ *
+ * Get ready to process incoming slc's and respond to them.
+ *
+ * The parameter getit is non-zero if it is necessary to grab a copy
+ * of the terminal control structures.
+ */
+       void
+start_slc(getit)
+       register int getit;
+{
+
+       slcchange = 0;
+       if (getit)
+               init_termbuf();
+       (void) sprintf((char *)slcbuf, "%c%c%c%c",
+                                       IAC, SB, TELOPT_LINEMODE, LM_SLC);
+       slcptr = slcbuf + 4;
+
+}  /* end of start_slc */
+
+/*
+ * end_slc
+ *
+ * Finish up the slc negotiation.  If something to send, then send it.
+ */
+       int
+end_slc(bufp)
+       register unsigned char **bufp;
+{
+       register int len;
+       void netflush();
+
+       /*
+        * If a change has occured, store the new terminal control
+        * structures back to the terminal driver.
+        */
+       if (slcchange) {
+               set_termbuf();
+       }
+
+       /*
+        * If the pty state has not yet been fully processed and there is a
+        * deferred slc request from the client, then do not send any
+        * sort of slc negotiation now.  We will respond to the client's
+        * request very soon.
+        */
+       if (def_slcbuf && (terminit() == 0)) {
+               return(0);
+       }
+
+       if (slcptr > (slcbuf + 4)) {
+               if (bufp) {
+                       *bufp = &slcbuf[4];
+                       return(slcptr - slcbuf - 4);
+               } else {
+                       (void) sprintf((char *)slcptr, "%c%c", IAC, SE);
+                       slcptr += 2;
+                       len = slcptr - slcbuf;
+                       writenet(slcbuf, len);
+                       netflush();  /* force it out immediately */
+                       DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2););
+               }
+       }
+       return (0);
+
+}  /* end of end_slc */
+
+/*
+ * process_slc
+ *
+ * Figure out what to do about the client's slc
+ */
+       void
+process_slc(func, flag, val)
+       register unsigned char func, flag;
+       register cc_t val;
+{
+       register int hislevel, mylevel, ack;
+
+       /*
+        * Ensure that we know something about this function
+        */
+       if (func > NSLC) {
+               add_slc(func, SLC_NOSUPPORT, 0);
+               return;
+       }
+
+       /*
+        * Process the special case requests of 0 SLC_DEFAULT 0
+        * and 0 SLC_VARIABLE 0.  Be a little forgiving here, don't
+        * worry about whether the value is actually 0 or not.
+        */
+       if (func == 0) {
+               if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) {
+                       default_slc();
+                       send_slc();
+               } else if (flag == SLC_VARIABLE) {
+                       send_slc();
+               }
+               return;
+       }
+
+       /*
+        * Appears to be a function that we know something about.  So
+        * get on with it and see what we know.
+        */
+
+       hislevel = flag & SLC_LEVELBITS;
+       mylevel = slctab[func].current.flag & SLC_LEVELBITS;
+       ack = flag & SLC_ACK;
+       /*
+        * ignore the command if:
+        * the function value and level are the same as what we already have;
+        * or the level is the same and the ack bit is set
+        */
+       if (hislevel == mylevel && (val == slctab[func].current.val || ack)) {
+               return;
+       } else if (ack) {
+               /*
+                * If we get here, we got an ack, but the levels don't match.
+                * This shouldn't happen.  If it does, it is probably because
+                * we have sent two requests to set a variable without getting
+                * a response between them, and this is the first response.
+                * So, ignore it, and wait for the next response.
+                */
+               return;
+       } else {
+               change_slc(func, flag, val);
+       }
+
+}  /* end of process_slc */
+
+/*
+ * change_slc
+ *
+ * Process a request to change one of our special characters.
+ * Compare client's request with what we are capable of supporting.
+ */
+       void
+change_slc(func, flag, val)
+       register char func, flag;
+       register cc_t val;
+{
+       register int hislevel, mylevel;
+
+       hislevel = flag & SLC_LEVELBITS;
+       mylevel = slctab[func].defset.flag & SLC_LEVELBITS;
+       /*
+        * If client is setting a function to NOSUPPORT
+        * or DEFAULT, then we can easily and directly
+        * accomodate the request.
+        */
+       if (hislevel == SLC_NOSUPPORT) {
+               slctab[func].current.flag = flag;
+               slctab[func].current.val = (cc_t)_POSIX_VDISABLE;
+               flag |= SLC_ACK;
+               add_slc(func, flag, val);
+               return;
+       }
+       if (hislevel == SLC_DEFAULT) {
+               /*
+                * Special case here.  If client tells us to use
+                * the default on a function we don't support, then
+                * return NOSUPPORT instead of what we may have as a
+                * default level of DEFAULT.
+                */
+               if (mylevel == SLC_DEFAULT) {
+                       slctab[func].current.flag = SLC_NOSUPPORT;
+               } else {
+                       slctab[func].current.flag = slctab[func].defset.flag;
+               }
+               slctab[func].current.val = slctab[func].defset.val;
+               add_slc(func, slctab[func].current.flag,
+                                               slctab[func].current.val);
+               return;
+       }
+
+       /*
+        * Client wants us to change to a new value or he
+        * is telling us that he can't change to our value.
+        * Some of the slc's we support and can change,
+        * some we do support but can't change,
+        * and others we don't support at all.
+        * If we can change it then we have a pointer to
+        * the place to put the new value, so change it,
+        * otherwise, continue the negotiation.
+        */
+       if (slctab[func].sptr) {
+               /*
+                * We can change this one.
+                */
+               slctab[func].current.val = val;
+               *(slctab[func].sptr) = val;
+               slctab[func].current.flag = flag;
+               flag |= SLC_ACK;
+               slcchange = 1;
+               add_slc(func, flag, val);
+       } else {
+               /*
+               * It is not possible for us to support this
+               * request as he asks.
+               *
+               * If our level is DEFAULT, then just ack whatever was
+               * sent.
+               *
+               * If he can't change and we can't change,
+               * then degenerate to NOSUPPORT.
+               *
+               * Otherwise we send our level back to him, (CANTCHANGE
+               * or NOSUPPORT) and if CANTCHANGE, send
+               * our value as well.
+               */
+               if (mylevel == SLC_DEFAULT) {
+                       slctab[func].current.flag = flag;
+                       slctab[func].current.val = val;
+                       flag |= SLC_ACK;
+               } else if (hislevel == SLC_CANTCHANGE &&
+                                   mylevel == SLC_CANTCHANGE) {
+                       flag &= ~SLC_LEVELBITS;
+                       flag |= SLC_NOSUPPORT;
+                       slctab[func].current.flag = flag;
+               } else {
+                       flag &= ~SLC_LEVELBITS;
+                       flag |= mylevel;
+                       slctab[func].current.flag = flag;
+                       if (mylevel == SLC_CANTCHANGE) {
+                               slctab[func].current.val =
+                                       slctab[func].defset.val;
+                               val = slctab[func].current.val;
+                       }
+               }
+               add_slc(func, flag, val);
+       }
+
+}  /* end of change_slc */
+
+#if    defined(USE_TERMIO) && (VEOF == VMIN)
+cc_t oldeofc = '\004';
+#endif
+
+/*
+ * check_slc
+ *
+ * Check the special characters in use and notify the client if any have
+ * changed.  Only those characters that are capable of being changed are
+ * likely to have changed.  If a local change occurs, kick the support level
+ * and flags up to the defaults.
+ */
+       void
+check_slc()
+{
+       register int i;
+
+       for (i = 1; i <= NSLC; i++) {
+#if    defined(USE_TERMIO) && (VEOF == VMIN)
+               /*
+                * In a perfect world this would be a neat little
+                * function.  But in this world, we should not notify
+                * client of changes to the VEOF char when
+                * ICANON is off, because it is not representing
+                * a special character.
+                */
+               if (i == SLC_EOF) {
+                       if (!tty_isediting())
+                               continue;
+                       else if (slctab[i].sptr)
+                               oldeofc = *(slctab[i].sptr);
+               }
+#endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */
+               if (slctab[i].sptr &&
+                               (*(slctab[i].sptr) != slctab[i].current.val)) {
+                       slctab[i].current.val = *(slctab[i].sptr);
+                       if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE)
+                               slctab[i].current.flag = SLC_NOSUPPORT;
+                       else
+                               slctab[i].current.flag = slctab[i].defset.flag;
+                       add_slc((unsigned char)i, slctab[i].current.flag,
+                                               slctab[i].current.val);
+               }
+       }
+}  /* check_slc */
+
+/*
+ * do_opt_slc
+ *
+ * Process an slc option buffer.  Defer processing of incoming slc's
+ * until after the terminal state has been processed.  Save the first slc
+ * request that comes along, but discard all others.
+ *
+ * ptr points to the beginning of the buffer, len is the length.
+ */
+       void
+do_opt_slc(ptr, len)
+       register unsigned char *ptr;
+       register int len;
+{
+       register unsigned char func, flag;
+       cc_t val;
+       register unsigned char *end = ptr + len;
+
+       if (terminit()) {  /* go ahead */
+               while (ptr < end) {
+                       func = *ptr++;
+                       if (ptr >= end) break;
+                       flag = *ptr++;
+                       if (ptr >= end) break;
+                       val = (cc_t)*ptr++;
+
+                       process_slc(func, flag, val);
+
+               }
+       } else {
+               /*
+                * save this slc buffer if it is the first, otherwise dump
+                * it.
+                */
+               if (def_slcbuf == (unsigned char *)0) {
+                       def_slclen = len;
+                       def_slcbuf = (unsigned char *)malloc((unsigned)len);
+                       if (def_slcbuf == (unsigned char *)0)
+                               return;  /* too bad */
+                       memmove(def_slcbuf, ptr, len);
+               }
+       }
+
+}  /* end of do_opt_slc */
+
+/*
+ * deferslc
+ *
+ * Do slc stuff that was deferred.
+ */
+       void
+deferslc()
+{
+       if (def_slcbuf) {
+               start_slc(1);
+               do_opt_slc(def_slcbuf, def_slclen);
+               (void) end_slc(0);
+               free(def_slcbuf);
+               def_slcbuf = (unsigned char *)0;
+               def_slclen = 0;
+       }
+
+}  /* end of deferslc */
+
+#endif /* LINEMODE */
diff --git a/telnetd.tproj/state.c b/telnetd.tproj/state.c
new file mode 100644 (file)
index 0000000..60de854
--- /dev/null
@@ -0,0 +1,1635 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)state.c    8.5 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include "telnetd.h"
+#if    defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+#endif
+
+unsigned char  doopt[] = { IAC, DO, '%', 'c', 0 };
+unsigned char  dont[] = { IAC, DONT, '%', 'c', 0 };
+unsigned char  will[] = { IAC, WILL, '%', 'c', 0 };
+unsigned char  wont[] = { IAC, WONT, '%', 'c', 0 };
+int    not42 = 1;
+
+/*
+ * Buffer for sub-options, and macros
+ * for suboptions buffer manipulations
+ */
+unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer;
+
+#define        SB_CLEAR()      subpointer = subbuffer
+#define        SB_TERM()       { subend = subpointer; SB_CLEAR(); }
+#define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
+                               *subpointer++ = (c); \
+                       }
+#define        SB_GET()        ((*subpointer++)&0xff)
+#define        SB_EOF()        (subpointer >= subend)
+#define        SB_LEN()        (subend - subpointer)
+
+#ifdef ENV_HACK
+unsigned char *subsave;
+#define SB_SAVE()      subsave = subpointer;
+#define        SB_RESTORE()    subpointer = subsave;
+#endif
+
+
+/*
+ * State for recv fsm
+ */
+#define        TS_DATA         0       /* base state */
+#define        TS_IAC          1       /* look for double IAC's */
+#define        TS_CR           2       /* CR-LF ->'s CR */
+#define        TS_SB           3       /* throw away begin's... */
+#define        TS_SE           4       /* ...end's (suboption negotiation) */
+#define        TS_WILL         5       /* will option negotiation */
+#define        TS_WONT         6       /* wont " */
+#define        TS_DO           7       /* do " */
+#define        TS_DONT         8       /* dont " */
+
+       void
+telrcv()
+{
+       register int c;
+       static int state = TS_DATA;
+#if    defined(CRAY2) && defined(UNICOS5)
+       char *opfrontp = pfrontp;
+#endif
+
+       while (ncc > 0) {
+               if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
+                       break;
+               c = *netip++ & 0377, ncc--;
+#ifdef ENCRYPTION
+               if (decrypt_input)
+                       c = (*decrypt_input)(c);
+#endif /* ENCRYPTION */
+               switch (state) {
+
+               case TS_CR:
+                       state = TS_DATA;
+                       /* Strip off \n or \0 after a \r */
+                       if ((c == 0) || (c == '\n')) {
+                               break;
+                       }
+                       /* FALL THROUGH */
+
+               case TS_DATA:
+                       if (c == IAC) {
+                               state = TS_IAC;
+                               break;
+                       }
+                       /*
+                        * We now map \r\n ==> \r for pragmatic reasons.
+                        * Many client implementations send \r\n when
+                        * the user hits the CarriageReturn key.
+                        *
+                        * We USED to map \r\n ==> \n, since \r\n says
+                        * that we want to be in column 1 of the next
+                        * printable line, and \n is the standard
+                        * unix way of saying that (\r is only good
+                        * if CRMOD is set, which it normally is).
+                        */
+                       if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
+                               int nc = *netip;
+#ifdef ENCRYPTION
+                               if (decrypt_input)
+                                       nc = (*decrypt_input)(nc & 0xff);
+#endif /* ENCRYPTION */
+#ifdef LINEMODE
+                               /*
+                                * If we are operating in linemode,
+                                * convert to local end-of-line.
+                                */
+                               if (linemode && (ncc > 0) && (('\n' == nc) ||
+                                        ((0 == nc) && tty_iscrnl())) ) {
+                                       netip++; ncc--;
+                                       c = '\n';
+                               } else
+#endif
+                               {
+#ifdef ENCRYPTION
+                                       if (decrypt_input)
+                                               (void)(*decrypt_input)(-1);
+#endif /* ENCRYPTION */
+                                       state = TS_CR;
+                               }
+                       }
+                       *pfrontp++ = c;
+                       break;
+
+               case TS_IAC:
+gotiac:                        switch (c) {
+
+                       /*
+                        * Send the process on the pty side an
+                        * interrupt.  Do this with a NULL or
+                        * interrupt char; depending on the tty mode.
+                        */
+                       case IP:
+                               DIAG(TD_OPTIONS,
+                                       printoption("td: recv IAC", c));
+                               interrupt();
+                               break;
+
+                       case BREAK:
+                               DIAG(TD_OPTIONS,
+                                       printoption("td: recv IAC", c));
+                               sendbrk();
+                               break;
+
+                       /*
+                        * Are You There?
+                        */
+                       case AYT:
+                               DIAG(TD_OPTIONS,
+                                       printoption("td: recv IAC", c));
+                               recv_ayt();
+                               break;
+
+                       /*
+                        * Abort Output
+                        */
+                       case AO:
+                           {
+                               DIAG(TD_OPTIONS,
+                                       printoption("td: recv IAC", c));
+                               ptyflush();     /* half-hearted */
+                               init_termbuf();
+
+                               if (slctab[SLC_AO].sptr &&
+                                   *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
+                                   *pfrontp++ =
+                                       (unsigned char)*slctab[SLC_AO].sptr;
+                               }
+
+                               netclear();     /* clear buffer back */
+                               *nfrontp++ = IAC;
+                               *nfrontp++ = DM;
+                               neturg = nfrontp-1; /* off by one XXX */
+                               DIAG(TD_OPTIONS,
+                                       printoption("td: send IAC", DM));
+                               break;
+                           }
+
+                       /*
+                        * Erase Character and
+                        * Erase Line
+                        */
+                       case EC:
+                       case EL:
+                           {
+                               cc_t ch;
+
+                               DIAG(TD_OPTIONS,
+                                       printoption("td: recv IAC", c));
+                               ptyflush();     /* half-hearted */
+                               init_termbuf();
+                               if (c == EC)
+                                       ch = *slctab[SLC_EC].sptr;
+                               else
+                                       ch = *slctab[SLC_EL].sptr;
+                               if (ch != (cc_t)(_POSIX_VDISABLE))
+                                       *pfrontp++ = (unsigned char)ch;
+                               break;
+                           }
+
+                       /*
+                        * Check for urgent data...
+                        */
+                       case DM:
+                               DIAG(TD_OPTIONS,
+                                       printoption("td: recv IAC", c));
+                               SYNCHing = stilloob(net);
+                               settimer(gotDM);
+                               break;
+
+
+                       /*
+                        * Begin option subnegotiation...
+                        */
+                       case SB:
+                               state = TS_SB;
+                               SB_CLEAR();
+                               continue;
+
+                       case WILL:
+                               state = TS_WILL;
+                               continue;
+
+                       case WONT:
+                               state = TS_WONT;
+                               continue;
+
+                       case DO:
+                               state = TS_DO;
+                               continue;
+
+                       case DONT:
+                               state = TS_DONT;
+                               continue;
+                       case EOR:
+                               if (his_state_is_will(TELOPT_EOR))
+                                       doeof();
+                               break;
+
+                       /*
+                        * Handle RFC 10xx Telnet linemode option additions
+                        * to command stream (EOF, SUSP, ABORT).
+                        */
+                       case xEOF:
+                               doeof();
+                               break;
+
+                       case SUSP:
+                               sendsusp();
+                               break;
+
+                       case ABORT:
+                               sendbrk();
+                               break;
+
+                       case IAC:
+                               *pfrontp++ = c;
+                               break;
+                       }
+                       state = TS_DATA;
+                       break;
+
+               case TS_SB:
+                       if (c == IAC) {
+                               state = TS_SE;
+                       } else {
+                               SB_ACCUM(c);
+                       }
+                       break;
+
+               case TS_SE:
+                       if (c != SE) {
+                               if (c != IAC) {
+                                       /*
+                                        * bad form of suboption negotiation.
+                                        * handle it in such a way as to avoid
+                                        * damage to local state.  Parse
+                                        * suboption buffer found so far,
+                                        * then treat remaining stream as
+                                        * another command sequence.
+                                        */
+
+                                       /* for DIAGNOSTICS */
+                                       SB_ACCUM(IAC);
+                                       SB_ACCUM(c);
+                                       subpointer -= 2;
+
+                                       SB_TERM();
+                                       suboption();
+                                       state = TS_IAC;
+                                       goto gotiac;
+                               }
+                               SB_ACCUM(c);
+                               state = TS_SB;
+                       } else {
+                               /* for DIAGNOSTICS */
+                               SB_ACCUM(IAC);
+                               SB_ACCUM(SE);
+                               subpointer -= 2;
+
+                               SB_TERM();
+                               suboption();    /* handle sub-option */
+                               state = TS_DATA;
+                       }
+                       break;
+
+               case TS_WILL:
+                       willoption(c);
+                       state = TS_DATA;
+                       continue;
+
+               case TS_WONT:
+                       wontoption(c);
+                       state = TS_DATA;
+                       continue;
+
+               case TS_DO:
+                       dooption(c);
+                       state = TS_DATA;
+                       continue;
+
+               case TS_DONT:
+                       dontoption(c);
+                       state = TS_DATA;
+                       continue;
+
+               default:
+                       syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
+                       printf("telnetd: panic state=%d\n", state);
+                       exit(1);
+               }
+       }
+#if    defined(CRAY2) && defined(UNICOS5)
+       if (!linemode) {
+               char    xptyobuf[BUFSIZ+NETSLOP];
+               char    xbuf2[BUFSIZ];
+               register char *cp;
+               int n = pfrontp - opfrontp, oc;
+               memmove(xptyobuf, opfrontp, n);
+               pfrontp = opfrontp;
+               pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP,
+                                       xbuf2, &oc, BUFSIZ);
+               for (cp = xbuf2; oc > 0; --oc)
+                       if ((*nfrontp++ = *cp++) == IAC)
+                               *nfrontp++ = IAC;
+       }
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+}  /* end of telrcv */
+
+/*
+ * The will/wont/do/dont state machines are based on Dave Borman's
+ * Telnet option processing state machine.
+ *
+ * These correspond to the following states:
+ *     my_state = the last negotiated state
+ *     want_state = what I want the state to go to
+ *     want_resp = how many requests I have sent
+ * All state defaults are negative, and resp defaults to 0.
+ *
+ * When initiating a request to change state to new_state:
+ *
+ * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
+ *     do nothing;
+ * } else {
+ *     want_state = new_state;
+ *     send new_state;
+ *     want_resp++;
+ * }
+ *
+ * When receiving new_state:
+ *
+ * if (want_resp) {
+ *     want_resp--;
+ *     if (want_resp && (new_state == my_state))
+ *             want_resp--;
+ * }
+ * if ((want_resp == 0) && (new_state != want_state)) {
+ *     if (ok_to_switch_to new_state)
+ *             want_state = new_state;
+ *     else
+ *             want_resp++;
+ *     send want_state;
+ * }
+ * my_state = new_state;
+ *
+ * Note that new_state is implied in these functions by the function itself.
+ * will and do imply positive new_state, wont and dont imply negative.
+ *
+ * Finally, there is one catch.  If we send a negative response to a
+ * positive request, my_state will be the positive while want_state will
+ * remain negative.  my_state will revert to negative when the negative
+ * acknowlegment arrives from the peer.  Thus, my_state generally tells
+ * us not only the last negotiated state, but also tells us what the peer
+ * wants to be doing as well.  It is important to understand this difference
+ * as we may wish to be processing data streams based on our desired state
+ * (want_state) or based on what the peer thinks the state is (my_state).
+ *
+ * This all works fine because if the peer sends a positive request, the data
+ * that we receive prior to negative acknowlegment will probably be affected
+ * by the positive state, and we can process it as such (if we can; if we
+ * can't then it really doesn't matter).  If it is that important, then the
+ * peer probably should be buffering until this option state negotiation
+ * is complete.
+ *
+ */
+       void
+send_do(option, init)
+       int option, init;
+{
+       if (init) {
+               if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
+                   his_want_state_is_will(option))
+                       return;
+               /*
+                * Special case for TELOPT_TM:  We send a DO, but pretend
+                * that we sent a DONT, so that we can send more DOs if
+                * we want to.
+                */
+               if (option == TELOPT_TM)
+                       set_his_want_state_wont(option);
+               else
+                       set_his_want_state_will(option);
+               do_dont_resp[option]++;
+       }
+       (void) sprintf(nfrontp, (char *)doopt, option);
+       nfrontp += sizeof (dont) - 2;
+
+       DIAG(TD_OPTIONS, printoption("td: send do", option));
+}
+
+#ifdef AUTHENTICATION
+extern void auth_request();
+#endif
+#ifdef LINEMODE
+extern void doclientstat();
+#endif
+#ifdef ENCRYPTION
+extern void encrypt_send_support();
+#endif /* ENCRYPTION */
+
+       void
+willoption(option)
+       int option;
+{
+       int changeok = 0;
+       void (*func)() = 0;
+
+       /*
+        * process input from peer.
+        */
+
+       DIAG(TD_OPTIONS, printoption("td: recv will", option));
+
+       if (do_dont_resp[option]) {
+               do_dont_resp[option]--;
+               if (do_dont_resp[option] && his_state_is_will(option))
+                       do_dont_resp[option]--;
+       }
+       if (do_dont_resp[option] == 0) {
+           if (his_want_state_is_wont(option)) {
+               switch (option) {
+
+               case TELOPT_BINARY:
+                       init_termbuf();
+                       tty_binaryin(1);
+                       set_termbuf();
+                       changeok++;
+                       break;
+
+               case TELOPT_ECHO:
+                       /*
+                        * See comments below for more info.
+                        */
+                       not42 = 0;      /* looks like a 4.2 system */
+                       break;
+
+               case TELOPT_TM:
+#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
+                       /*
+                        * This telnetd implementation does not really
+                        * support timing marks, it just uses them to
+                        * support the kludge linemode stuff.  If we
+                        * receive a will or wont TM in response to our
+                        * do TM request that may have been sent to
+                        * determine kludge linemode support, process
+                        * it, otherwise TM should get a negative
+                        * response back.
+                        */
+                       /*
+                        * Handle the linemode kludge stuff.
+                        * If we are not currently supporting any
+                        * linemode at all, then we assume that this
+                        * is the client telling us to use kludge
+                        * linemode in response to our query.  Set the
+                        * linemode type that is to be supported, note
+                        * that the client wishes to use linemode, and
+                        * eat the will TM as though it never arrived.
+                        */
+                       if (lmodetype < KLUDGE_LINEMODE) {
+                               lmodetype = KLUDGE_LINEMODE;
+                               clientstat(TELOPT_LINEMODE, WILL, 0);
+                               send_wont(TELOPT_SGA, 1);
+                       } else if (lmodetype == NO_AUTOKLUDGE) {
+                               lmodetype = KLUDGE_OK;
+                       }
+#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+                       /*
+                        * We never respond to a WILL TM, and
+                        * we leave the state WONT.
+                        */
+                       return;
+
+               case TELOPT_LFLOW:
+                       /*
+                        * If we are going to support flow control
+                        * option, then don't worry peer that we can't
+                        * change the flow control characters.
+                        */
+                       slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
+                       slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
+                       slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
+                       slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
+               case TELOPT_TTYPE:
+               case TELOPT_SGA:
+               case TELOPT_NAWS:
+               case TELOPT_TSPEED:
+               case TELOPT_XDISPLOC:
+               case TELOPT_NEW_ENVIRON:
+               case TELOPT_OLD_ENVIRON:
+                       changeok++;
+                       break;
+
+#ifdef LINEMODE
+               case TELOPT_LINEMODE:
+# ifdef        KLUDGELINEMODE
+                       /*
+                        * Note client's desire to use linemode.
+                        */
+                       lmodetype = REAL_LINEMODE;
+# endif        /* KLUDGELINEMODE */
+                       func = doclientstat;
+                       changeok++;
+                       break;
+#endif /* LINEMODE */
+
+#ifdef AUTHENTICATION
+               case TELOPT_AUTHENTICATION:
+                       func = auth_request;
+                       changeok++;
+                       break;
+#endif
+
+#ifdef ENCRYPTION
+               case TELOPT_ENCRYPT:
+                       func = encrypt_send_support;
+                       changeok++;
+                       break;
+#endif /* ENCRYPTION */
+
+               default:
+                       break;
+               }
+               if (changeok) {
+                       set_his_want_state_will(option);
+                       send_do(option, 0);
+               } else {
+                       do_dont_resp[option]++;
+                       send_dont(option, 0);
+               }
+           } else {
+               /*
+                * Option processing that should happen when
+                * we receive conformation of a change in
+                * state that we had requested.
+                */
+               switch (option) {
+               case TELOPT_ECHO:
+                       not42 = 0;      /* looks like a 4.2 system */
+                       /*
+                        * Egads, he responded "WILL ECHO".  Turn
+                        * it off right now!
+                        */
+                       send_dont(option, 1);
+                       /*
+                        * "WILL ECHO".  Kludge upon kludge!
+                        * A 4.2 client is now echoing user input at
+                        * the tty.  This is probably undesireable and
+                        * it should be stopped.  The client will
+                        * respond WONT TM to the DO TM that we send to
+                        * check for kludge linemode.  When the WONT TM
+                        * arrives, linemode will be turned off and a
+                        * change propogated to the pty.  This change
+                        * will cause us to process the new pty state
+                        * in localstat(), which will notice that
+                        * linemode is off and send a WILL ECHO
+                        * so that we are properly in character mode and
+                        * all is well.
+                        */
+                       break;
+#ifdef LINEMODE
+               case TELOPT_LINEMODE:
+# ifdef        KLUDGELINEMODE
+                       /*
+                        * Note client's desire to use linemode.
+                        */
+                       lmodetype = REAL_LINEMODE;
+# endif        /* KLUDGELINEMODE */
+                       func = doclientstat;
+                       break;
+#endif /* LINEMODE */
+
+#ifdef AUTHENTICATION
+               case TELOPT_AUTHENTICATION:
+                       func = auth_request;
+                       break;
+#endif
+
+#ifdef ENCRYPTION
+               case TELOPT_ENCRYPT:
+                       func = encrypt_send_support;
+                       break;
+#endif /* ENCRYPTION */
+               case TELOPT_LFLOW:
+                       func = flowstat;
+                       break;
+               }
+           }
+       }
+       set_his_state_will(option);
+       if (func)
+               (*func)();
+}  /* end of willoption */
+
+       void
+send_dont(option, init)
+       int option, init;
+{
+       if (init) {
+               if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) ||
+                   his_want_state_is_wont(option))
+                       return;
+               set_his_want_state_wont(option);
+               do_dont_resp[option]++;
+       }
+       (void) sprintf(nfrontp, (char *)dont, option);
+       nfrontp += sizeof (doopt) - 2;
+
+       DIAG(TD_OPTIONS, printoption("td: send dont", option));
+}
+
+       void
+wontoption(option)
+       int option;
+{
+       /*
+        * Process client input.
+        */
+
+       DIAG(TD_OPTIONS, printoption("td: recv wont", option));
+
+       if (do_dont_resp[option]) {
+               do_dont_resp[option]--;
+               if (do_dont_resp[option] && his_state_is_wont(option))
+                       do_dont_resp[option]--;
+       }
+       if (do_dont_resp[option] == 0) {
+           if (his_want_state_is_will(option)) {
+               /* it is always ok to change to negative state */
+               switch (option) {
+               case TELOPT_ECHO:
+                       not42 = 1; /* doesn't seem to be a 4.2 system */
+                       break;
+
+               case TELOPT_BINARY:
+                       init_termbuf();
+                       tty_binaryin(0);
+                       set_termbuf();
+                       break;
+
+#ifdef LINEMODE
+               case TELOPT_LINEMODE:
+# ifdef        KLUDGELINEMODE
+                       /*
+                        * If real linemode is supported, then client is
+                        * asking to turn linemode off.
+                        */
+                       if (lmodetype != REAL_LINEMODE)
+                               break;
+# endif        /* KLUDGELINEMODE */
+                       clientstat(TELOPT_LINEMODE, WONT, 0);
+                       break;
+#endif /* LINEMODE */
+
+               case TELOPT_TM:
+                       /*
+                        * If we get a WONT TM, and had sent a DO TM,
+                        * don't respond with a DONT TM, just leave it
+                        * as is.  Short circut the state machine to
+                        * achive this.
+                        */
+                       set_his_want_state_wont(TELOPT_TM);
+                       return;
+
+               case TELOPT_LFLOW:
+                       /*
+                        * If we are not going to support flow control
+                        * option, then let peer know that we can't
+                        * change the flow control characters.
+                        */
+                       slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
+                       slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
+                       slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
+                       slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
+                       break;
+
+#if    defined(AUTHENTICATION)
+               case TELOPT_AUTHENTICATION:
+                       auth_finished(0, AUTH_REJECT);
+                       break;
+#endif
+
+               /*
+                * For options that we might spin waiting for
+                * sub-negotiation, if the client turns off the
+                * option rather than responding to the request,
+                * we have to treat it here as if we got a response
+                * to the sub-negotiation, (by updating the timers)
+                * so that we'll break out of the loop.
+                */
+               case TELOPT_TTYPE:
+                       settimer(ttypesubopt);
+                       break;
+
+               case TELOPT_TSPEED:
+                       settimer(tspeedsubopt);
+                       break;
+
+               case TELOPT_XDISPLOC:
+                       settimer(xdisplocsubopt);
+                       break;
+
+               case TELOPT_OLD_ENVIRON:
+                       settimer(oenvironsubopt);
+                       break;
+
+               case TELOPT_NEW_ENVIRON:
+                       settimer(environsubopt);
+                       break;
+
+               default:
+                       break;
+               }
+               set_his_want_state_wont(option);
+               if (his_state_is_will(option))
+                       send_dont(option, 0);
+           } else {
+               switch (option) {
+               case TELOPT_TM:
+#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
+                       if (lmodetype < NO_AUTOKLUDGE) {
+                               lmodetype = NO_LINEMODE;
+                               clientstat(TELOPT_LINEMODE, WONT, 0);
+                               send_will(TELOPT_SGA, 1);
+                               send_will(TELOPT_ECHO, 1);
+                       }
+#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+                       break;
+
+#if    defined(AUTHENTICATION)
+               case TELOPT_AUTHENTICATION:
+                       auth_finished(0, AUTH_REJECT);
+                       break;
+#endif
+               default:
+                       break;
+               }
+           }
+       }
+       set_his_state_wont(option);
+
+}  /* end of wontoption */
+
+       void
+send_will(option, init)
+       int option, init;
+{
+       if (init) {
+               if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
+                   my_want_state_is_will(option))
+                       return;
+               set_my_want_state_will(option);
+               will_wont_resp[option]++;
+       }
+       (void) sprintf(nfrontp, (char *)will, option);
+       nfrontp += sizeof (doopt) - 2;
+
+       DIAG(TD_OPTIONS, printoption("td: send will", option));
+}
+
+#if    !defined(LINEMODE) || !defined(KLUDGELINEMODE)
+/*
+ * When we get a DONT SGA, we will try once to turn it
+ * back on.  If the other side responds DONT SGA, we
+ * leave it at that.  This is so that when we talk to
+ * clients that understand KLUDGELINEMODE but not LINEMODE,
+ * we'll keep them in char-at-a-time mode.
+ */
+int turn_on_sga = 0;
+#endif
+
+       void
+dooption(option)
+       int option;
+{
+       int changeok = 0;
+
+       /*
+        * Process client input.
+        */
+
+       DIAG(TD_OPTIONS, printoption("td: recv do", option));
+
+       if (will_wont_resp[option]) {
+               will_wont_resp[option]--;
+               if (will_wont_resp[option] && my_state_is_will(option))
+                       will_wont_resp[option]--;
+       }
+       if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
+               switch (option) {
+               case TELOPT_ECHO:
+#ifdef LINEMODE
+# ifdef        KLUDGELINEMODE
+                       if (lmodetype == NO_LINEMODE)
+# else
+                       if (his_state_is_wont(TELOPT_LINEMODE))
+# endif
+#endif
+                       {
+                               init_termbuf();
+                               tty_setecho(1);
+                               set_termbuf();
+                       }
+                       changeok++;
+                       break;
+
+               case TELOPT_BINARY:
+                       init_termbuf();
+                       tty_binaryout(1);
+                       set_termbuf();
+                       changeok++;
+                       break;
+
+               case TELOPT_SGA:
+#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
+                       /*
+                        * If kludge linemode is in use, then we must
+                        * process an incoming do SGA for linemode
+                        * purposes.
+                        */
+                       if (lmodetype == KLUDGE_LINEMODE) {
+                               /*
+                                * Receipt of "do SGA" in kludge
+                                * linemode is the peer asking us to
+                                * turn off linemode.  Make note of
+                                * the request.
+                                */
+                               clientstat(TELOPT_LINEMODE, WONT, 0);
+                               /*
+                                * If linemode did not get turned off
+                                * then don't tell peer that we did.
+                                * Breaking here forces a wont SGA to
+                                * be returned.
+                                */
+                               if (linemode)
+                                       break;
+                       }
+#else
+                       turn_on_sga = 0;
+#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+                       changeok++;
+                       break;
+
+               case TELOPT_STATUS:
+                       changeok++;
+                       break;
+
+               case TELOPT_TM:
+                       /*
+                        * Special case for TM.  We send a WILL, but
+                        * pretend we sent a WONT.
+                        */
+                       send_will(option, 0);
+                       set_my_want_state_wont(option);
+                       set_my_state_wont(option);
+                       return;
+
+               case TELOPT_LOGOUT:
+                       /*
+                        * When we get a LOGOUT option, respond
+                        * with a WILL LOGOUT, make sure that
+                        * it gets written out to the network,
+                        * and then just go away...
+                        */
+                       set_my_want_state_will(TELOPT_LOGOUT);
+                       send_will(TELOPT_LOGOUT, 0);
+                       set_my_state_will(TELOPT_LOGOUT);
+                       (void)netflush();
+                       cleanup(0);
+                       /* NOT REACHED */
+                       break;
+
+#ifdef ENCRYPTION
+               case TELOPT_ENCRYPT:
+                       changeok++;
+                       break;
+#endif /* ENCRYPTION */
+               case TELOPT_LINEMODE:
+               case TELOPT_TTYPE:
+               case TELOPT_NAWS:
+               case TELOPT_TSPEED:
+               case TELOPT_LFLOW:
+               case TELOPT_XDISPLOC:
+#ifdef TELOPT_ENVIRON
+               case TELOPT_NEW_ENVIRON:
+#endif
+               case TELOPT_OLD_ENVIRON:
+               default:
+                       break;
+               }
+               if (changeok) {
+                       set_my_want_state_will(option);
+                       send_will(option, 0);
+               } else {
+                       will_wont_resp[option]++;
+                       send_wont(option, 0);
+               }
+       }
+       set_my_state_will(option);
+
+}  /* end of dooption */
+
+       void
+send_wont(option, init)
+       int option, init;
+{
+       if (init) {
+               if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
+                   my_want_state_is_wont(option))
+                       return;
+               set_my_want_state_wont(option);
+               will_wont_resp[option]++;
+       }
+       (void) sprintf(nfrontp, (char *)wont, option);
+       nfrontp += sizeof (wont) - 2;
+
+       DIAG(TD_OPTIONS, printoption("td: send wont", option));
+}
+
+       void
+dontoption(option)
+       int option;
+{
+       /*
+        * Process client input.
+        */
+
+
+       DIAG(TD_OPTIONS, printoption("td: recv dont", option));
+
+       if (will_wont_resp[option]) {
+               will_wont_resp[option]--;
+               if (will_wont_resp[option] && my_state_is_wont(option))
+                       will_wont_resp[option]--;
+       }
+       if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
+               switch (option) {
+               case TELOPT_BINARY:
+                       init_termbuf();
+                       tty_binaryout(0);
+                       set_termbuf();
+                       break;
+
+               case TELOPT_ECHO:       /* we should stop echoing */
+#ifdef LINEMODE
+# ifdef        KLUDGELINEMODE
+                       if ((lmodetype != REAL_LINEMODE) &&
+                           (lmodetype != KLUDGE_LINEMODE))
+# else
+                       if (his_state_is_wont(TELOPT_LINEMODE))
+# endif
+#endif
+                       {
+                               init_termbuf();
+                               tty_setecho(0);
+                               set_termbuf();
+                       }
+                       break;
+
+               case TELOPT_SGA:
+#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
+                       /*
+                        * If kludge linemode is in use, then we
+                        * must process an incoming do SGA for
+                        * linemode purposes.
+                        */
+                       if ((lmodetype == KLUDGE_LINEMODE) ||
+                           (lmodetype == KLUDGE_OK)) {
+                               /*
+                                * The client is asking us to turn
+                                * linemode on.
+                                */
+                               lmodetype = KLUDGE_LINEMODE;
+                               clientstat(TELOPT_LINEMODE, WILL, 0);
+                               /*
+                                * If we did not turn line mode on,
+                                * then what do we say?  Will SGA?
+                                * This violates design of telnet.
+                                * Gross.  Very Gross.
+                                */
+                       }
+                       break;
+#else
+                       set_my_want_state_wont(option);
+                       if (my_state_is_will(option))
+                               send_wont(option, 0);
+                       set_my_state_wont(option);
+                       if (turn_on_sga ^= 1)
+                               send_will(option, 1);
+                       return;
+#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+
+               default:
+                       break;
+               }
+
+               set_my_want_state_wont(option);
+               if (my_state_is_will(option))
+                       send_wont(option, 0);
+       }
+       set_my_state_wont(option);
+
+}  /* end of dontoption */
+
+#ifdef ENV_HACK
+int env_ovar = -1;
+int env_ovalue = -1;
+#else  /* ENV_HACK */
+# define env_ovar OLD_ENV_VAR
+# define env_ovalue OLD_ENV_VALUE
+#endif /* ENV_HACK */
+
+/*
+ * suboption()
+ *
+ *     Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ *
+ *     Currently we recognize:
+ *
+ *     Terminal type is
+ *     Linemode
+ *     Window size
+ *     Terminal speed
+ */
+       void
+suboption()
+{
+    register int subchar;
+
+    DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
+
+    subchar = SB_GET();
+    switch (subchar) {
+    case TELOPT_TSPEED: {
+       register int xspeed, rspeed;
+
+       if (his_state_is_wont(TELOPT_TSPEED))   /* Ignore if option disabled */
+               break;
+
+       settimer(tspeedsubopt);
+
+       if (SB_EOF() || SB_GET() != TELQUAL_IS)
+               return;
+
+       xspeed = atoi((char *)subpointer);
+
+       while (SB_GET() != ',' && !SB_EOF());
+       if (SB_EOF())
+               return;
+
+       rspeed = atoi((char *)subpointer);
+       clientstat(TELOPT_TSPEED, xspeed, rspeed);
+
+       break;
+
+    }  /* end of case TELOPT_TSPEED */
+
+    case TELOPT_TTYPE: {               /* Yaaaay! */
+       static char terminalname[41];
+
+       if (his_state_is_wont(TELOPT_TTYPE))    /* Ignore if option disabled */
+               break;
+       settimer(ttypesubopt);
+
+       if (SB_EOF() || SB_GET() != TELQUAL_IS) {
+           return;             /* ??? XXX but, this is the most robust */
+       }
+
+       terminaltype = terminalname;
+
+       while ((terminaltype < (terminalname + sizeof terminalname-1)) &&
+                                                                   !SB_EOF()) {
+           register int c;
+
+           c = SB_GET();
+           if (isupper(c)) {
+               c = tolower(c);
+           }
+           *terminaltype++ = c;    /* accumulate name */
+       }
+       *terminaltype = 0;
+       terminaltype = terminalname;
+       break;
+    }  /* end of case TELOPT_TTYPE */
+
+    case TELOPT_NAWS: {
+       register int xwinsize, ywinsize;
+
+       if (his_state_is_wont(TELOPT_NAWS))     /* Ignore if option disabled */
+               break;
+
+       if (SB_EOF())
+               return;
+       xwinsize = SB_GET() << 8;
+       if (SB_EOF())
+               return;
+       xwinsize |= SB_GET();
+       if (SB_EOF())
+               return;
+       ywinsize = SB_GET() << 8;
+       if (SB_EOF())
+               return;
+       ywinsize |= SB_GET();
+       clientstat(TELOPT_NAWS, xwinsize, ywinsize);
+
+       break;
+
+    }  /* end of case TELOPT_NAWS */
+
+#ifdef LINEMODE
+    case TELOPT_LINEMODE: {
+       register int request;
+
+       if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */
+               break;
+       /*
+        * Process linemode suboptions.
+        */
+       if (SB_EOF())
+           break;              /* garbage was sent */
+       request = SB_GET();     /* get will/wont */
+
+       if (SB_EOF())
+           break;              /* another garbage check */
+
+       if (request == LM_SLC) {  /* SLC is not preceeded by WILL or WONT */
+               /*
+                * Process suboption buffer of slc's
+                */
+               start_slc(1);
+               do_opt_slc(subpointer, subend - subpointer);
+               (void) end_slc(0);
+               break;
+       } else if (request == LM_MODE) {
+               if (SB_EOF())
+                   return;
+               useeditmode = SB_GET();  /* get mode flag */
+               clientstat(LM_MODE, 0, 0);
+               break;
+       }
+
+       if (SB_EOF())
+           break;
+       switch (SB_GET()) {  /* what suboption? */
+       case LM_FORWARDMASK:
+               /*
+                * According to spec, only server can send request for
+                * forwardmask, and client can only return a positive response.
+                * So don't worry about it.
+                */
+
+       default:
+               break;
+       }
+       break;
+    }  /* end of case TELOPT_LINEMODE */
+#endif
+    case TELOPT_STATUS: {
+       int mode;
+
+       if (SB_EOF())
+           break;
+       mode = SB_GET();
+       switch (mode) {
+       case TELQUAL_SEND:
+           if (my_state_is_will(TELOPT_STATUS))
+               send_status();
+           break;
+
+       case TELQUAL_IS:
+           break;
+
+       default:
+           break;
+       }
+       break;
+    }  /* end of case TELOPT_STATUS */
+
+    case TELOPT_XDISPLOC: {
+       if (SB_EOF() || SB_GET() != TELQUAL_IS)
+               return;
+       settimer(xdisplocsubopt);
+       subpointer[SB_LEN()] = '\0';
+       (void)setenv("DISPLAY", (char *)subpointer, 1);
+       break;
+    }  /* end of case TELOPT_XDISPLOC */
+
+#ifdef TELOPT_NEW_ENVIRON
+    case TELOPT_NEW_ENVIRON:
+#endif
+    case TELOPT_OLD_ENVIRON: {
+       register int c;
+       register char *cp, *varp, *valp;
+
+       if (SB_EOF())
+               return;
+       c = SB_GET();
+       if (c == TELQUAL_IS) {
+               if (subchar == TELOPT_OLD_ENVIRON)
+                       settimer(oenvironsubopt);
+               else
+                       settimer(environsubopt);
+       } else if (c != TELQUAL_INFO) {
+               return;
+       }
+
+#ifdef TELOPT_NEW_ENVIRON
+       if (subchar == TELOPT_NEW_ENVIRON) {
+           while (!SB_EOF()) {
+               c = SB_GET();
+               if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
+                       break;
+           }
+       } else
+#endif
+       {
+#ifdef ENV_HACK
+           /*
+            * We only want to do this if we haven't already decided
+            * whether or not the other side has its VALUE and VAR
+            * reversed.
+            */
+           if (env_ovar < 0) {
+               register int last = -1;         /* invalid value */
+               int empty = 0;
+               int got_var = 0, got_value = 0, got_uservar = 0;
+
+               /*
+                * The other side might have its VALUE and VAR values
+                * reversed.  To be interoperable, we need to determine
+                * which way it is.  If the first recognized character
+                * is a VAR or VALUE, then that will tell us what
+                * type of client it is.  If the fist recognized
+                * character is a USERVAR, then we continue scanning
+                * the suboption looking for two consecutive
+                * VAR or VALUE fields.  We should not get two
+                * consecutive VALUE fields, so finding two
+                * consecutive VALUE or VAR fields will tell us
+                * what the client is.
+                */
+               SB_SAVE();
+               while (!SB_EOF()) {
+                       c = SB_GET();
+                       switch(c) {
+                       case OLD_ENV_VAR:
+                               if (last < 0 || last == OLD_ENV_VAR
+                                   || (empty && (last == OLD_ENV_VALUE)))
+                                       goto env_ovar_ok;
+                               got_var++;
+                               last = OLD_ENV_VAR;
+                               break;
+                       case OLD_ENV_VALUE:
+                               if (last < 0 || last == OLD_ENV_VALUE
+                                   || (empty && (last == OLD_ENV_VAR)))
+                                       goto env_ovar_wrong;
+                               got_value++;
+                               last = OLD_ENV_VALUE;
+                               break;
+                       case ENV_USERVAR:
+                               /* count strings of USERVAR as one */
+                               if (last != ENV_USERVAR)
+                                       got_uservar++;
+                               if (empty) {
+                                       if (last == OLD_ENV_VALUE)
+                                               goto env_ovar_ok;
+                                       if (last == OLD_ENV_VAR)
+                                               goto env_ovar_wrong;
+                               }
+                               last = ENV_USERVAR;
+                               break;
+                       case ENV_ESC:
+                               if (!SB_EOF())
+                                       c = SB_GET();
+                               /* FALL THROUGH */
+                       default:
+                               empty = 0;
+                               continue;
+                       }
+                       empty = 1;
+               }
+               if (empty) {
+                       if (last == OLD_ENV_VALUE)
+                               goto env_ovar_ok;
+                       if (last == OLD_ENV_VAR)
+                               goto env_ovar_wrong;
+               }
+               /*
+                * Ok, the first thing was a USERVAR, and there
+                * are not two consecutive VAR or VALUE commands,
+                * and none of the VAR or VALUE commands are empty.
+                * If the client has sent us a well-formed option,
+                * then the number of VALUEs received should always
+                * be less than or equal to the number of VARs and
+                * USERVARs received.
+                *
+                * If we got exactly as many VALUEs as VARs and
+                * USERVARs, the client has the same definitions.
+                *
+                * If we got exactly as many VARs as VALUEs and
+                * USERVARS, the client has reversed definitions.
+                */
+               if (got_uservar + got_var == got_value) {
+           env_ovar_ok:
+                       env_ovar = OLD_ENV_VAR;
+                       env_ovalue = OLD_ENV_VALUE;
+               } else if (got_uservar + got_value == got_var) {
+           env_ovar_wrong:
+                       env_ovar = OLD_ENV_VALUE;
+                       env_ovalue = OLD_ENV_VAR;
+                       DIAG(TD_OPTIONS, {sprintf(nfrontp,
+                               "ENVIRON VALUE and VAR are reversed!\r\n");
+                               nfrontp += strlen(nfrontp);});
+
+               }
+           }
+           SB_RESTORE();
+#endif
+
+           while (!SB_EOF()) {
+               c = SB_GET();
+               if ((c == env_ovar) || (c == ENV_USERVAR))
+                       break;
+           }
+       }
+
+       if (SB_EOF())
+               return;
+
+       cp = varp = (char *)subpointer;
+       valp = 0;
+
+       while (!SB_EOF()) {
+               c = SB_GET();
+               if (subchar == TELOPT_OLD_ENVIRON) {
+                       if (c == env_ovar)
+                               c = NEW_ENV_VAR;
+                       else if (c == env_ovalue)
+                               c = NEW_ENV_VALUE;
+               }
+               switch (c) {
+
+               case NEW_ENV_VALUE:
+                       *cp = '\0';
+                       cp = valp = (char *)subpointer;
+                       break;
+
+               case NEW_ENV_VAR:
+               case ENV_USERVAR:
+                       *cp = '\0';
+                       if (valp)
+                               (void)setenv(varp, valp, 1);
+                       else
+                               unsetenv(varp);
+                       cp = varp = (char *)subpointer;
+                       valp = 0;
+                       break;
+
+               case ENV_ESC:
+                       if (SB_EOF())
+                               break;
+                       c = SB_GET();
+                       /* FALL THROUGH */
+               default:
+                       *cp++ = c;
+                       break;
+               }
+       }
+       *cp = '\0';
+       if (valp)
+               (void)setenv(varp, valp, 1);
+       else
+               unsetenv(varp);
+       break;
+    }  /* end of case TELOPT_NEW_ENVIRON */
+#if    defined(AUTHENTICATION)
+    case TELOPT_AUTHENTICATION:
+       if (SB_EOF())
+               break;
+       switch(SB_GET()) {
+       case TELQUAL_SEND:
+       case TELQUAL_REPLY:
+               /*
+                * These are sent by us and cannot be sent by
+                * the client.
+                */
+               break;
+       case TELQUAL_IS:
+               auth_is(subpointer, SB_LEN());
+               break;
+       case TELQUAL_NAME:
+               auth_name(subpointer, SB_LEN());
+               break;
+       }
+       break;
+#endif
+#ifdef ENCRYPTION
+    case TELOPT_ENCRYPT:
+       if (SB_EOF())
+               break;
+       switch(SB_GET()) {
+       case ENCRYPT_SUPPORT:
+               encrypt_support(subpointer, SB_LEN());
+               break;
+       case ENCRYPT_IS:
+               encrypt_is(subpointer, SB_LEN());
+               break;
+       case ENCRYPT_REPLY:
+               encrypt_reply(subpointer, SB_LEN());
+               break;
+       case ENCRYPT_START:
+               encrypt_start(subpointer, SB_LEN());
+               break;
+       case ENCRYPT_END:
+               encrypt_end();
+               break;
+       case ENCRYPT_REQSTART:
+               encrypt_request_start(subpointer, SB_LEN());
+               break;
+       case ENCRYPT_REQEND:
+               /*
+                * We can always send an REQEND so that we cannot
+                * get stuck encrypting.  We should only get this
+                * if we have been able to get in the correct mode
+                * anyhow.
+                */
+               encrypt_request_end();
+               break;
+       case ENCRYPT_ENC_KEYID:
+               encrypt_enc_keyid(subpointer, SB_LEN());
+               break;
+       case ENCRYPT_DEC_KEYID:
+               encrypt_dec_keyid(subpointer, SB_LEN());
+               break;
+       default:
+               break;
+       }
+       break;
+#endif /* ENCRYPTION */
+
+    default:
+       break;
+    }  /* end of switch */
+
+}  /* end of suboption */
+
+       void
+doclientstat()
+{
+       clientstat(TELOPT_LINEMODE, WILL, 0);
+}
+
+#define        ADD(c)   *ncp++ = c
+#define        ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; }
+       void
+send_status()
+{
+       unsigned char statusbuf[256];
+       register unsigned char *ncp;
+       register unsigned char i;
+
+       ncp = statusbuf;
+
+       netflush();     /* get rid of anything waiting to go out */
+
+       ADD(IAC);
+       ADD(SB);
+       ADD(TELOPT_STATUS);
+       ADD(TELQUAL_IS);
+
+       /*
+        * We check the want_state rather than the current state,
+        * because if we received a DO/WILL for an option that we
+        * don't support, and the other side didn't send a DONT/WONT
+        * in response to our WONT/DONT, then the "state" will be
+        * WILL/DO, and the "want_state" will be WONT/DONT.  We
+        * need to go by the latter.
+        */
+       for (i = 0; i < (unsigned char)NTELOPTS; i++) {
+               if (my_want_state_is_will(i)) {
+                       ADD(WILL);
+                       ADD_DATA(i);
+               }
+               if (his_want_state_is_will(i)) {
+                       ADD(DO);
+                       ADD_DATA(i);
+               }
+       }
+
+       if (his_want_state_is_will(TELOPT_LFLOW)) {
+               ADD(SB);
+               ADD(TELOPT_LFLOW);
+               if (flowmode) {
+                       ADD(LFLOW_ON);
+               } else {
+                       ADD(LFLOW_OFF);
+               }
+               ADD(SE);
+
+               if (restartany >= 0) {
+                       ADD(SB);
+                       ADD(TELOPT_LFLOW);
+                       if (restartany) {
+                               ADD(LFLOW_RESTART_ANY);
+                       } else {
+                               ADD(LFLOW_RESTART_XON);
+                       }
+                       ADD(SE);
+               }
+       }
+
+#ifdef LINEMODE
+       if (his_want_state_is_will(TELOPT_LINEMODE)) {
+               unsigned char *cp, *cpe;
+               int len;
+
+               ADD(SB);
+               ADD(TELOPT_LINEMODE);
+               ADD(LM_MODE);
+               ADD_DATA(editmode);
+               ADD(SE);
+
+               ADD(SB);
+               ADD(TELOPT_LINEMODE);
+               ADD(LM_SLC);
+               start_slc(0);
+               send_slc();
+               len = end_slc(&cp);
+               for (cpe = cp + len; cp < cpe; cp++)
+                       ADD_DATA(*cp);
+               ADD(SE);
+       }
+#endif /* LINEMODE */
+
+       ADD(IAC);
+       ADD(SE);
+
+       writenet(statusbuf, ncp - statusbuf);
+       netflush();     /* Send it on its way */
+
+       DIAG(TD_OPTIONS,
+               {printsub('>', statusbuf, ncp - statusbuf); netflush();});
+}
diff --git a/telnetd.tproj/sys_term.c b/telnetd.tproj/sys_term.c
new file mode 100644 (file)
index 0000000..61d116e
--- /dev/null
@@ -0,0 +1,2306 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)sys_term.c 8.4 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include "telnetd.h"
+#include "pathnames.h"
+
+#if    defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+#endif
+
+#if defined(CRAY) || defined(__hpux)
+# define PARENT_DOES_UTMP
+#endif
+
+#ifdef NEWINIT
+#include <initreq.h>
+int    utmp_len = MAXHOSTNAMELEN;      /* sizeof(init_request.host) */
+#else  /* NEWINIT*/
+# ifdef        UTMPX
+# include <utmpx.h>
+struct utmpx wtmp;
+# else
+# include <utmp.h>
+struct utmp wtmp;
+# endif /* UTMPX */
+
+int    utmp_len = sizeof(wtmp.ut_host);
+# ifndef PARENT_DOES_UTMP
+char   wtmpf[] = "/usr/adm/wtmp";
+char   utmpf[] = "/var/run/utmp";
+# else /* PARENT_DOES_UTMP */
+char   wtmpf[] = "/etc/wtmp";
+# endif /* PARENT_DOES_UTMP */
+
+# ifdef CRAY
+#include <tmpdir.h>
+#include <sys/wait.h>
+#  if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
+#   define UNICOS7x
+#  endif
+
+#  ifdef UNICOS7x
+#include <sys/sysv.h>
+#include <sys/secstat.h>
+extern int secflag;
+extern struct sysv sysv;
+#  endif /* UNICOS7x */
+# endif        /* CRAY */
+#endif /* NEWINIT */
+
+#ifdef STREAMSPTY
+#include <sac.h>
+#include <sys/stropts.h>
+#endif
+
+#define SCPYN(a, b)    (void) strncpy(a, b, sizeof(a))
+#define SCMPN(a, b)    strncmp(a, b, sizeof(a))
+
+#ifdef STREAMS
+#include <sys/stream.h>
+#endif
+#ifdef __hpux
+#include <sys/resource.h>
+#include <sys/proc.h>
+#endif
+#include <sys/tty.h>
+#ifdef t_erase
+#undef t_erase
+#undef t_kill
+#undef t_intrc
+#undef t_quitc
+#undef t_startc
+#undef t_stopc
+#undef t_eofc
+#undef t_brkc
+#undef t_suspc
+#undef t_dsuspc
+#undef t_rprntc
+#undef t_flushc
+#undef t_werasc
+#undef t_lnextc
+#endif
+
+#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
+# define EXTPROC 0400
+#endif
+
+#ifndef        USE_TERMIO
+struct termbuf {
+       struct sgttyb sg;
+       struct tchars tc;
+       struct ltchars ltc;
+       int state;
+       int lflags;
+} termbuf, termbuf2;
+# define       cfsetospeed(tp, val)    (tp)->sg.sg_ospeed = (val)
+# define       cfsetispeed(tp, val)    (tp)->sg.sg_ispeed = (val)
+# define       cfgetospeed(tp)         (tp)->sg.sg_ospeed
+# define       cfgetispeed(tp)         (tp)->sg.sg_ispeed
+#else  /* USE_TERMIO */
+# ifdef        SYSV_TERMIO
+#      define termios termio
+# endif
+# ifndef       TCSANOW
+#  ifdef TCSETS
+#   define     TCSANOW         TCSETS
+#   define     TCSADRAIN       TCSETSW
+#   define     tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
+#  else
+#   ifdef TCSETA
+#    define    TCSANOW         TCSETA
+#    define    TCSADRAIN       TCSETAW
+#    define    tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
+#   else
+#    define    TCSANOW         TIOCSETA
+#    define    TCSADRAIN       TIOCSETAW
+#    define    tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
+#   endif
+#  endif
+#  define      tcsetattr(f, a, t)      ioctl(f, a, t)
+#  define      cfsetospeed(tp, val)    (tp)->c_cflag &= ~CBAUD; \
+                                       (tp)->c_cflag |= (val)
+#  define      cfgetospeed(tp)         ((tp)->c_cflag & CBAUD)
+#  ifdef CIBAUD
+#   define     cfsetispeed(tp, val)    (tp)->c_cflag &= ~CIBAUD; \
+                                       (tp)->c_cflag |= ((val)<<IBSHIFT)
+#   define     cfgetispeed(tp)         (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
+#  else
+#   define     cfsetispeed(tp, val)    (tp)->c_cflag &= ~CBAUD; \
+                                       (tp)->c_cflag |= (val)
+#   define     cfgetispeed(tp)         ((tp)->c_cflag & CBAUD)
+#  endif
+# endif /* TCSANOW */
+struct termios termbuf, termbuf2;      /* pty control structure */
+# ifdef  STREAMSPTY
+int ttyfd = -1;
+# endif
+#endif /* USE_TERMIO */
+
+/*
+ * init_termbuf()
+ * copy_termbuf(cp)
+ * set_termbuf()
+ *
+ * These three routines are used to get and set the "termbuf" structure
+ * to and from the kernel.  init_termbuf() gets the current settings.
+ * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
+ * set_termbuf() writes the structure into the kernel.
+ */
+
+       void
+init_termbuf()
+{
+#ifndef        USE_TERMIO
+       (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
+       (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
+       (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
+# ifdef        TIOCGSTATE
+       (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
+# endif
+#else
+# ifdef  STREAMSPTY
+       (void) tcgetattr(ttyfd, &termbuf);
+# else
+       (void) tcgetattr(pty, &termbuf);
+# endif
+#endif
+       termbuf2 = termbuf;
+}
+
+#if    defined(LINEMODE) && defined(TIOCPKT_IOCTL)
+       void
+copy_termbuf(cp, len)
+       char *cp;
+       int len;
+{
+       if (len > sizeof(termbuf))
+               len = sizeof(termbuf);
+       memmove((char *)&termbuf, cp, len);
+       termbuf2 = termbuf;
+}
+#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
+
+       void
+set_termbuf()
+{
+       /*
+        * Only make the necessary changes.
+        */
+#ifndef        USE_TERMIO
+       if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
+                                                       sizeof(termbuf.sg)))
+               (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
+       if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
+                                                       sizeof(termbuf.tc)))
+               (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
+       if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
+                                                       sizeof(termbuf.ltc)))
+               (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
+       if (termbuf.lflags != termbuf2.lflags)
+               (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
+#else  /* USE_TERMIO */
+       if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
+# ifdef  STREAMSPTY
+               (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
+# else
+               (void) tcsetattr(pty, TCSANOW, &termbuf);
+# endif
+# if   defined(CRAY2) && defined(UNICOS5)
+       needtermstat = 1;
+# endif
+#endif /* USE_TERMIO */
+}
+
+
+/*
+ * spcset(func, valp, valpp)
+ *
+ * This function takes various special characters (func), and
+ * sets *valp to the current value of that character, and
+ * *valpp to point to where in the "termbuf" structure that
+ * value is kept.
+ *
+ * It returns the SLC_ level of support for this function.
+ */
+
+#ifndef        USE_TERMIO
+       int
+spcset(func, valp, valpp)
+       int func;
+       cc_t *valp;
+       cc_t **valpp;
+{
+       switch(func) {
+       case SLC_EOF:
+               *valp = termbuf.tc.t_eofc;
+               *valpp = (cc_t *)&termbuf.tc.t_eofc;
+               return(SLC_VARIABLE);
+       case SLC_EC:
+               *valp = termbuf.sg.sg_erase;
+               *valpp = (cc_t *)&termbuf.sg.sg_erase;
+               return(SLC_VARIABLE);
+       case SLC_EL:
+               *valp = termbuf.sg.sg_kill;
+               *valpp = (cc_t *)&termbuf.sg.sg_kill;
+               return(SLC_VARIABLE);
+       case SLC_IP:
+               *valp = termbuf.tc.t_intrc;
+               *valpp = (cc_t *)&termbuf.tc.t_intrc;
+               return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+       case SLC_ABORT:
+               *valp = termbuf.tc.t_quitc;
+               *valpp = (cc_t *)&termbuf.tc.t_quitc;
+               return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+       case SLC_XON:
+               *valp = termbuf.tc.t_startc;
+               *valpp = (cc_t *)&termbuf.tc.t_startc;
+               return(SLC_VARIABLE);
+       case SLC_XOFF:
+               *valp = termbuf.tc.t_stopc;
+               *valpp = (cc_t *)&termbuf.tc.t_stopc;
+               return(SLC_VARIABLE);
+       case SLC_AO:
+               *valp = termbuf.ltc.t_flushc;
+               *valpp = (cc_t *)&termbuf.ltc.t_flushc;
+               return(SLC_VARIABLE);
+       case SLC_SUSP:
+               *valp = termbuf.ltc.t_suspc;
+               *valpp = (cc_t *)&termbuf.ltc.t_suspc;
+               return(SLC_VARIABLE);
+       case SLC_EW:
+               *valp = termbuf.ltc.t_werasc;
+               *valpp = (cc_t *)&termbuf.ltc.t_werasc;
+               return(SLC_VARIABLE);
+       case SLC_RP:
+               *valp = termbuf.ltc.t_rprntc;
+               *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
+               return(SLC_VARIABLE);
+       case SLC_LNEXT:
+               *valp = termbuf.ltc.t_lnextc;
+               *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
+               return(SLC_VARIABLE);
+       case SLC_FORW1:
+               *valp = termbuf.tc.t_brkc;
+               *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
+               return(SLC_VARIABLE);
+       case SLC_BRK:
+       case SLC_SYNCH:
+       case SLC_AYT:
+       case SLC_EOR:
+               *valp = (cc_t)0;
+               *valpp = (cc_t *)0;
+               return(SLC_DEFAULT);
+       default:
+               *valp = (cc_t)0;
+               *valpp = (cc_t *)0;
+               return(SLC_NOSUPPORT);
+       }
+}
+
+#else  /* USE_TERMIO */
+
+       int
+spcset(func, valp, valpp)
+       int func;
+       cc_t *valp;
+       cc_t **valpp;
+{
+
+#define        setval(a, b)    *valp = termbuf.c_cc[a]; \
+                       *valpp = &termbuf.c_cc[a]; \
+                       return(b);
+#define        defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
+
+       switch(func) {
+       case SLC_EOF:
+               setval(VEOF, SLC_VARIABLE);
+       case SLC_EC:
+               setval(VERASE, SLC_VARIABLE);
+       case SLC_EL:
+               setval(VKILL, SLC_VARIABLE);
+       case SLC_IP:
+               setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+       case SLC_ABORT:
+               setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+       case SLC_XON:
+#ifdef VSTART
+               setval(VSTART, SLC_VARIABLE);
+#else
+               defval(0x13);
+#endif
+       case SLC_XOFF:
+#ifdef VSTOP
+               setval(VSTOP, SLC_VARIABLE);
+#else
+               defval(0x11);
+#endif
+       case SLC_EW:
+#ifdef VWERASE
+               setval(VWERASE, SLC_VARIABLE);
+#else
+               defval(0);
+#endif
+       case SLC_RP:
+#ifdef VREPRINT
+               setval(VREPRINT, SLC_VARIABLE);
+#else
+               defval(0);
+#endif
+       case SLC_LNEXT:
+#ifdef VLNEXT
+               setval(VLNEXT, SLC_VARIABLE);
+#else
+               defval(0);
+#endif
+       case SLC_AO:
+#if    !defined(VDISCARD) && defined(VFLUSHO)
+# define VDISCARD VFLUSHO
+#endif
+#ifdef VDISCARD
+               setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
+#else
+               defval(0);
+#endif
+       case SLC_SUSP:
+#ifdef VSUSP
+               setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
+#else
+               defval(0);
+#endif
+#ifdef VEOL
+       case SLC_FORW1:
+               setval(VEOL, SLC_VARIABLE);
+#endif
+#ifdef VEOL2
+       case SLC_FORW2:
+               setval(VEOL2, SLC_VARIABLE);
+#endif
+       case SLC_AYT:
+#ifdef VSTATUS
+               setval(VSTATUS, SLC_VARIABLE);
+#else
+               defval(0);
+#endif
+
+       case SLC_BRK:
+       case SLC_SYNCH:
+       case SLC_EOR:
+               defval(0);
+
+       default:
+               *valp = 0;
+               *valpp = 0;
+               return(SLC_NOSUPPORT);
+       }
+}
+#endif /* USE_TERMIO */
+
+#ifdef CRAY
+/*
+ * getnpty()
+ *
+ * Return the number of pty's configured into the system.
+ */
+       int
+getnpty()
+{
+#ifdef _SC_CRAY_NPTY
+       int numptys;
+
+       if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
+               return numptys;
+       else
+#endif /* _SC_CRAY_NPTY */
+               return 128;
+}
+#endif /* CRAY */
+
+#ifndef        convex
+/*
+ * getpty()
+ *
+ * Allocate a pty.  As a side effect, the external character
+ * array "line" contains the name of the slave side.
+ *
+ * Returns the file descriptor of the opened pty.
+ */
+#ifndef __APPLE__
+#ifndef        __GNUC__
+char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+#else
+static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+char *line = Xline;
+#endif
+#ifdef CRAY
+char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+#endif /* CRAY */
+#endif /* !NeXT */
+
+       int
+getpty(ptynum)
+int *ptynum;
+{
+       register int p;
+#ifdef STREAMSPTY
+       int t;
+       char *ptsname();
+
+       p = open("/dev/ptmx", 2);
+       if (p > 0) {
+               grantpt(p);
+               unlockpt(p);
+               strcpy(line, ptsname(p));
+               return(p);
+       }
+
+#else  /* ! STREAMSPTY */
+#ifndef CRAY
+       register char *cp, *p1, *p2;
+       register int i;
+#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
+       int dummy;
+#endif
+
+#ifndef        __hpux
+       (void) sprintf(line, "/dev/ptyXX");
+       p1 = &line[8];
+       p2 = &line[9];
+#else
+       (void) sprintf(line, "/dev/ptym/ptyXX");
+       p1 = &line[13];
+       p2 = &line[14];
+#endif
+
+       for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
+               struct stat stb;
+
+               *p1 = *cp;
+               *p2 = '0';
+               /*
+                * This stat() check is just to keep us from
+                * looping through all 256 combinations if there
+                * aren't that many ptys available.
+                */
+               if (stat(line, &stb) < 0)
+                       break;
+               for (i = 0; i < 16; i++) {
+                       *p2 = "0123456789abcdef"[i];
+                       p = open(line, 2);
+                       if (p > 0) {
+#ifndef        __hpux
+                               line[5] = 't';
+#else
+                               for (p1 = &line[8]; *p1; p1++)
+                                       *p1 = *(p1+1);
+                               line[9] = 't';
+#endif
+                               chown(line, 0, 0);
+                               chmod(line, 0600);
+#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
+                               if (ioctl(p, TIOCGPGRP, &dummy) == 0
+                                   || errno != EIO) {
+                                       chmod(line, 0666);
+                                       close(p);
+                                       line[5] = 'p';
+                               } else
+#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
+                                       return(p);
+                       }
+               }
+       }
+#else  /* CRAY */
+       extern lowpty, highpty;
+       struct stat sb;
+
+       for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
+               (void) sprintf(myline, "/dev/pty/%03d", *ptynum);
+               p = open(myline, 2);
+               if (p < 0)
+                       continue;
+               (void) sprintf(line, "/dev/ttyp%03d", *ptynum);
+               /*
+                * Here are some shenanigans to make sure that there
+                * are no listeners lurking on the line.
+                */
+               if(stat(line, &sb) < 0) {
+                       (void) close(p);
+                       continue;
+               }
+               if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
+                       chown(line, 0, 0);
+                       chmod(line, 0600);
+                       (void)close(p);
+                       p = open(myline, 2);
+                       if (p < 0)
+                               continue;
+               }
+               /*
+                * Now it should be safe...check for accessability.
+                */
+               if (access(line, 6) == 0)
+                       return(p);
+               else {
+                       /* no tty side to pty so skip it */
+                       (void) close(p);
+               }
+       }
+#endif /* CRAY */
+#endif /* STREAMSPTY */
+       return(-1);
+}
+#endif /* convex */
+
+#ifdef LINEMODE
+/*
+ * tty_flowmode()      Find out if flow control is enabled or disabled.
+ * tty_linemode()      Find out if linemode (external processing) is enabled.
+ * tty_setlinemod(on)  Turn on/off linemode.
+ * tty_isecho()                Find out if echoing is turned on.
+ * tty_setecho(on)     Enable/disable character echoing.
+ * tty_israw()         Find out if terminal is in RAW mode.
+ * tty_binaryin(on)    Turn on/off BINARY on input.
+ * tty_binaryout(on)   Turn on/off BINARY on output.
+ * tty_isediting()     Find out if line editing is enabled.
+ * tty_istrapsig()     Find out if signal trapping is enabled.
+ * tty_setedit(on)     Turn on/off line editing.
+ * tty_setsig(on)      Turn on/off signal trapping.
+ * tty_issofttab()     Find out if tab expansion is enabled.
+ * tty_setsofttab(on)  Turn on/off soft tab expansion.
+ * tty_islitecho()     Find out if typed control chars are echoed literally
+ * tty_setlitecho()    Turn on/off literal echo of control chars
+ * tty_tspeed(val)     Set transmit speed to val.
+ * tty_rspeed(val)     Set receive speed to val.
+ */
+
+#ifdef convex
+static int linestate;
+#endif
+
+       int
+tty_linemode()
+{
+#ifndef convex
+#ifndef        USE_TERMIO
+       return(termbuf.state & TS_EXTPROC);
+#else
+       return(termbuf.c_lflag & EXTPROC);
+#endif
+#else
+       return(linestate);
+#endif
+}
+
+       void
+tty_setlinemode(on)
+       int on;
+{
+#ifdef TIOCEXT
+# ifndef convex
+       set_termbuf();
+# else
+       linestate = on;
+# endif
+       (void) ioctl(pty, TIOCEXT, (char *)&on);
+# ifndef convex
+       init_termbuf();
+# endif
+#else  /* !TIOCEXT */
+# ifdef        EXTPROC
+       if (on)
+               termbuf.c_lflag |= EXTPROC;
+       else
+               termbuf.c_lflag &= ~EXTPROC;
+# endif
+#endif /* TIOCEXT */
+}
+#endif /* LINEMODE */
+
+       int
+tty_isecho()
+{
+#ifndef USE_TERMIO
+       return (termbuf.sg.sg_flags & ECHO);
+#else
+       return (termbuf.c_lflag & ECHO);
+#endif
+}
+
+       int
+tty_flowmode()
+{
+#ifndef USE_TERMIO
+       return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
+#else
+       return((termbuf.c_iflag & IXON) ? 1 : 0);
+#endif
+}
+
+       int
+tty_restartany()
+{
+#ifndef USE_TERMIO
+# ifdef        DECCTQ
+       return((termbuf.lflags & DECCTQ) ? 0 : 1);
+# else
+       return(-1);
+# endif
+#else
+       return((termbuf.c_iflag & IXANY) ? 1 : 0);
+#endif
+}
+
+       void
+tty_setecho(on)
+       int on;
+{
+#ifndef        USE_TERMIO
+       if (on)
+               termbuf.sg.sg_flags |= ECHO|CRMOD;
+       else
+               termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
+#else
+       if (on)
+               termbuf.c_lflag |= ECHO;
+       else
+               termbuf.c_lflag &= ~ECHO;
+#endif
+}
+
+       int
+tty_israw()
+{
+#ifndef USE_TERMIO
+       return(termbuf.sg.sg_flags & RAW);
+#else
+       return(!(termbuf.c_lflag & ICANON));
+#endif
+}
+
+#if    defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       int
+tty_setraw(on)
+{
+#  ifndef USE_TERMIO
+       if (on)
+               termbuf.sg.sg_flags |= RAW;
+       else
+               termbuf.sg.sg_flags &= ~RAW;
+#  else
+       if (on)
+               termbuf.c_lflag &= ~ICANON;
+       else
+               termbuf.c_lflag |= ICANON;
+#  endif
+}
+#endif
+
+       void
+tty_binaryin(on)
+       int on;
+{
+#ifndef        USE_TERMIO
+       if (on)
+               termbuf.lflags |= LPASS8;
+       else
+               termbuf.lflags &= ~LPASS8;
+#else
+       if (on) {
+               termbuf.c_iflag &= ~ISTRIP;
+       } else {
+               termbuf.c_iflag |= ISTRIP;
+       }
+#endif
+}
+
+       void
+tty_binaryout(on)
+       int on;
+{
+#ifndef        USE_TERMIO
+       if (on)
+               termbuf.lflags |= LLITOUT;
+       else
+               termbuf.lflags &= ~LLITOUT;
+#else
+       if (on) {
+               termbuf.c_cflag &= ~(CSIZE|PARENB);
+               termbuf.c_cflag |= CS8;
+               termbuf.c_oflag &= ~OPOST;
+       } else {
+               termbuf.c_cflag &= ~CSIZE;
+               termbuf.c_cflag |= CS7|PARENB;
+               termbuf.c_oflag |= OPOST;
+       }
+#endif
+}
+
+       int
+tty_isbinaryin()
+{
+#ifndef        USE_TERMIO
+       return(termbuf.lflags & LPASS8);
+#else
+       return(!(termbuf.c_iflag & ISTRIP));
+#endif
+}
+
+       int
+tty_isbinaryout()
+{
+#ifndef        USE_TERMIO
+       return(termbuf.lflags & LLITOUT);
+#else
+       return(!(termbuf.c_oflag&OPOST));
+#endif
+}
+
+#ifdef LINEMODE
+       int
+tty_isediting()
+{
+#ifndef USE_TERMIO
+       return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
+#else
+       return(termbuf.c_lflag & ICANON);
+#endif
+}
+
+       int
+tty_istrapsig()
+{
+#ifndef USE_TERMIO
+       return(!(termbuf.sg.sg_flags&RAW));
+#else
+       return(termbuf.c_lflag & ISIG);
+#endif
+}
+
+       void
+tty_setedit(on)
+       int on;
+{
+#ifndef USE_TERMIO
+       if (on)
+               termbuf.sg.sg_flags &= ~CBREAK;
+       else
+               termbuf.sg.sg_flags |= CBREAK;
+#else
+       if (on)
+               termbuf.c_lflag |= ICANON;
+       else
+               termbuf.c_lflag &= ~ICANON;
+#endif
+}
+
+       void
+tty_setsig(on)
+       int on;
+{
+#ifndef        USE_TERMIO
+       if (on)
+               ;
+#else
+       if (on)
+               termbuf.c_lflag |= ISIG;
+       else
+               termbuf.c_lflag &= ~ISIG;
+#endif
+}
+#endif /* LINEMODE */
+
+       int
+tty_issofttab()
+{
+#ifndef        USE_TERMIO
+       return (termbuf.sg.sg_flags & XTABS);
+#else
+# ifdef        OXTABS
+       return (termbuf.c_oflag & OXTABS);
+# endif
+# ifdef        TABDLY
+       return ((termbuf.c_oflag & TABDLY) == TAB3);
+# endif
+#endif
+}
+
+       void
+tty_setsofttab(on)
+       int on;
+{
+#ifndef        USE_TERMIO
+       if (on)
+               termbuf.sg.sg_flags |= XTABS;
+       else
+               termbuf.sg.sg_flags &= ~XTABS;
+#else
+       if (on) {
+# ifdef        OXTABS
+               termbuf.c_oflag |= OXTABS;
+# endif
+# ifdef        TABDLY
+               termbuf.c_oflag &= ~TABDLY;
+               termbuf.c_oflag |= TAB3;
+# endif
+       } else {
+# ifdef        OXTABS
+               termbuf.c_oflag &= ~OXTABS;
+# endif
+# ifdef        TABDLY
+               termbuf.c_oflag &= ~TABDLY;
+               termbuf.c_oflag |= TAB0;
+# endif
+       }
+#endif
+}
+
+       int
+tty_islitecho()
+{
+#ifndef        USE_TERMIO
+       return (!(termbuf.lflags & LCTLECH));
+#else
+# ifdef        ECHOCTL
+       return (!(termbuf.c_lflag & ECHOCTL));
+# endif
+# ifdef        TCTLECH
+       return (!(termbuf.c_lflag & TCTLECH));
+# endif
+# if   !defined(ECHOCTL) && !defined(TCTLECH)
+       return (0);     /* assumes ctl chars are echoed '^x' */
+# endif
+#endif
+}
+
+       void
+tty_setlitecho(on)
+       int on;
+{
+#ifndef        USE_TERMIO
+       if (on)
+               termbuf.lflags &= ~LCTLECH;
+       else
+               termbuf.lflags |= LCTLECH;
+#else
+# ifdef        ECHOCTL
+       if (on)
+               termbuf.c_lflag &= ~ECHOCTL;
+       else
+               termbuf.c_lflag |= ECHOCTL;
+# endif
+# ifdef        TCTLECH
+       if (on)
+               termbuf.c_lflag &= ~TCTLECH;
+       else
+               termbuf.c_lflag |= TCTLECH;
+# endif
+#endif
+}
+
+       int
+tty_iscrnl()
+{
+#ifndef        USE_TERMIO
+       return (termbuf.sg.sg_flags & CRMOD);
+#else
+       return (termbuf.c_iflag & ICRNL);
+#endif
+}
+
+/*
+ * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
+ */
+#if B4800 != 4800
+#define        DECODE_BAUD
+#endif
+
+#ifdef DECODE_BAUD
+
+/*
+ * A table of available terminal speeds
+ */
+struct termspeeds {
+       int     speed;
+       int     value;
+} termspeeds[] = {
+       { 0,      B0 },      { 50,    B50 },    { 75,     B75 },
+       { 110,    B110 },    { 134,   B134 },   { 150,    B150 },
+       { 200,    B200 },    { 300,   B300 },   { 600,    B600 },
+       { 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
+       { 4800,   B4800 },
+#ifdef B7200
+       { 7200,  B7200 },
+#endif
+       { 9600,   B9600 },
+#ifdef B14400
+       { 14400,  B14400 },
+#endif
+#ifdef B19200
+       { 19200,  B19200 },
+#endif
+#ifdef B28800
+       { 28800,  B28800 },
+#endif
+#ifdef B38400
+       { 38400,  B38400 },
+#endif
+#ifdef B57600
+       { 57600,  B57600 },
+#endif
+#ifdef B115200
+       { 115200, B115200 },
+#endif
+#ifdef B230400
+       { 230400, B230400 },
+#endif
+       { -1,     0 }
+};
+#endif /* DECODE_BUAD */
+
+       void
+tty_tspeed(val)
+       int val;
+{
+#ifdef DECODE_BAUD
+       register struct termspeeds *tp;
+
+       for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
+               ;
+       if (tp->speed == -1)    /* back up to last valid value */
+               --tp;
+       cfsetospeed(&termbuf, tp->value);
+#else  /* DECODE_BUAD */
+       cfsetospeed(&termbuf, val);
+#endif /* DECODE_BUAD */
+}
+
+       void
+tty_rspeed(val)
+       int val;
+{
+#ifdef DECODE_BAUD
+       register struct termspeeds *tp;
+
+       for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
+               ;
+       if (tp->speed == -1)    /* back up to last valid value */
+               --tp;
+       cfsetispeed(&termbuf, tp->value);
+#else  /* DECODE_BAUD */
+       cfsetispeed(&termbuf, val);
+#endif /* DECODE_BAUD */
+}
+
+#if    defined(CRAY2) && defined(UNICOS5)
+       int
+tty_isnewmap()
+{
+       return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
+                       !(termbuf.c_oflag & ONLRET));
+}
+#endif
+
+#ifdef PARENT_DOES_UTMP
+# ifndef NEWINIT
+extern struct utmp wtmp;
+extern char wtmpf[];
+# else /* NEWINIT */
+int    gotalarm;
+
+       /* ARGSUSED */
+       void
+nologinproc(sig)
+       int sig;
+{
+       gotalarm++;
+}
+# endif        /* NEWINIT */
+#endif /* PARENT_DOES_UTMP */
+
+#ifndef        NEWINIT
+# ifdef PARENT_DOES_UTMP
+extern void utmp_sig_init P((void));
+extern void utmp_sig_reset P((void));
+extern void utmp_sig_wait P((void));
+extern void utmp_sig_notify P((int));
+# endif /* PARENT_DOES_UTMP */
+#endif
+
+/*
+ * getptyslave()
+ *
+ * Open the slave side of the pty, and do any initialization
+ * that is necessary.  The return value is a file descriptor
+ * for the slave side.
+ */
+       int
+getptyslave()
+{
+       register int t = -1;
+
+#if    !defined(CRAY) || !defined(NEWINIT)
+# ifdef        LINEMODE
+       int waslm;
+# endif
+# ifdef        TIOCGWINSZ
+       struct winsize ws;
+       extern int def_row, def_col;
+# endif
+       extern int def_tspeed, def_rspeed;
+       /*
+        * Opening the slave side may cause initilization of the
+        * kernel tty structure.  We need remember the state of
+        *      if linemode was turned on
+        *      terminal window size
+        *      terminal speed
+        * so that we can re-set them if we need to.
+        */
+# ifdef        LINEMODE
+       waslm = tty_linemode();
+# endif
+
+
+       /*
+        * Make sure that we don't have a controlling tty, and
+        * that we are the session (process group) leader.
+        */
+# ifdef        TIOCNOTTY
+       t = open(_PATH_TTY, O_RDWR);
+       if (t >= 0) {
+               (void) ioctl(t, TIOCNOTTY, (char *)0);
+               (void) close(t);
+       }
+# endif
+
+
+# ifdef PARENT_DOES_UTMP
+       /*
+        * Wait for our parent to get the utmp stuff to get done.
+        */
+       utmp_sig_wait();
+# endif
+
+       t = cleanopen(line);
+       if (t < 0)
+               fatalperror(net, line);
+
+#ifdef  STREAMSPTY
+#ifdef USE_TERMIO
+       ttyfd = t;
+#endif
+       if (ioctl(t, I_PUSH, "ptem") < 0)
+               fatal(net, "I_PUSH ptem");
+       if (ioctl(t, I_PUSH, "ldterm") < 0)
+               fatal(net, "I_PUSH ldterm");
+       if (ioctl(t, I_PUSH, "ttcompat") < 0)
+               fatal(net, "I_PUSH ttcompat");
+       if (ioctl(pty, I_PUSH, "pckt") < 0)
+               fatal(net, "I_PUSH pckt");
+#endif
+
+       /*
+        * set up the tty modes as we like them to be.
+        */
+       init_termbuf();
+# ifdef        TIOCGWINSZ
+       if (def_row || def_col) {
+               memset((char *)&ws, 0, sizeof(ws));
+               ws.ws_col = def_col;
+               ws.ws_row = def_row;
+               (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
+       }
+# endif
+
+       /*
+        * Settings for sgtty based systems
+        */
+# ifndef       USE_TERMIO
+       termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
+# endif        /* USE_TERMIO */
+
+       /*
+        * Settings for UNICOS (and HPUX)
+        */
+# if defined(CRAY) || defined(__hpux)
+       termbuf.c_oflag = OPOST|ONLCR|TAB3;
+       termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
+       termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
+       termbuf.c_cflag = EXTB|HUPCL|CS8;
+# endif
+
+       /*
+        * Settings for all other termios/termio based
+        * systems, other than 4.4BSD.  In 4.4BSD the
+        * kernel does the initial terminal setup.
+        */
+# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
+#  ifndef      OXTABS
+#   define OXTABS      0
+#  endif
+       termbuf.c_lflag |= ECHO;
+       termbuf.c_oflag |= ONLCR|OXTABS;
+       termbuf.c_iflag |= ICRNL;
+       termbuf.c_iflag &= ~IXOFF;
+# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
+       tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
+       tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
+# ifdef        LINEMODE
+       if (waslm)
+               tty_setlinemode(1);
+# endif        /* LINEMODE */
+
+       /*
+        * Set the tty modes, and make this our controlling tty.
+        */
+       set_termbuf();
+       if (login_tty(t) == -1)
+               fatalperror(net, "login_tty");
+#endif /* !defined(CRAY) || !defined(NEWINIT) */
+       if (net > 2)
+               (void) close(net);
+#if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       /*
+        * Leave the pty open so that we can write out the rlogin
+        * protocol for /bin/login, if the authentication works.
+        */
+#else
+       if (pty > 2) {
+               (void) close(pty);
+               pty = -1;
+       }
+#endif
+}
+
+#if    !defined(CRAY) || !defined(NEWINIT)
+#ifndef        O_NOCTTY
+#define        O_NOCTTY        0
+#endif
+/*
+ * Open the specified slave side of the pty,
+ * making sure that we have a clean tty.
+ */
+       int
+cleanopen(line)
+       char *line;
+{
+       register int t;
+#ifdef UNICOS7x
+       struct secstat secbuf;
+#endif /* UNICOS7x */
+
+#ifndef STREAMSPTY
+       /*
+        * Make sure that other people can't open the
+        * slave side of the connection.
+        */
+       (void) chown(line, 0, 0);
+       (void) chmod(line, 0600);
+#endif
+
+# if !defined(CRAY) && (BSD > 43)
+       (void) revoke(line);
+# endif
+#ifdef UNICOS7x
+       if (secflag) {
+               if (secstat(line, &secbuf) < 0)
+                       return(-1);
+               if (setulvl(secbuf.st_slevel) < 0)
+                       return(-1);
+               if (setucmp(secbuf.st_compart) < 0)
+                       return(-1);
+       }
+#endif /* UNICOS7x */
+
+       t = open(line, O_RDWR|O_NOCTTY);
+
+#ifdef UNICOS7x
+       if (secflag) {
+               if (setulvl(sysv.sy_minlvl) < 0)
+                       return(-1);
+               if (setucmp(0) < 0)
+                       return(-1);
+       }
+#endif /* UNICOS7x */
+
+       if (t < 0)
+               return(-1);
+
+       /*
+        * Hangup anybody else using this ttyp, then reopen it for
+        * ourselves.
+        */
+# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
+       (void) signal(SIGHUP, SIG_IGN);
+       vhangup();
+       (void) signal(SIGHUP, SIG_DFL);
+       t = open(line, O_RDWR|O_NOCTTY);
+       if (t < 0)
+               return(-1);
+# endif
+# if   defined(CRAY) && defined(TCVHUP)
+       {
+               register int i;
+               (void) signal(SIGHUP, SIG_IGN);
+               (void) ioctl(t, TCVHUP, (char *)0);
+               (void) signal(SIGHUP, SIG_DFL);
+
+#ifdef UNICOS7x
+               if (secflag) {
+                       if (secstat(line, &secbuf) < 0)
+                               return(-1);
+                       if (setulvl(secbuf.st_slevel) < 0)
+                               return(-1);
+                       if (setucmp(secbuf.st_compart) < 0)
+                               return(-1);
+               }
+#endif /* UNICOS7x */
+
+               i = open(line, O_RDWR);
+
+#ifdef UNICOS7x
+               if (secflag) {
+                       if (setulvl(sysv.sy_minlvl) < 0)
+                               return(-1);
+                       if (setucmp(0) < 0)
+                               return(-1);
+               }
+#endif /* UNICOS7x */
+
+               if (i < 0)
+                       return(-1);
+               (void) close(t);
+               t = i;
+       }
+# endif        /* defined(CRAY) && defined(TCVHUP) */
+       return(t);
+}
+#endif /* !defined(CRAY) || !defined(NEWINIT) */
+
+#if BSD <= 43
+
+       int
+login_tty(t)
+       int t;
+{
+       if (setsid() < 0) {
+#ifdef ultrix
+               /*
+                * The setsid() may have failed because we
+                * already have a pgrp == pid.  Zero out
+                * our pgrp and try again...
+                */
+               if ((setpgrp(0, 0) < 0) || (setsid() < 0))
+#endif
+                       fatalperror(net, "setsid()");
+       }
+# ifdef        TIOCSCTTY
+       if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
+               fatalperror(net, "ioctl(sctty)");
+#  if defined(CRAY)
+       /*
+        * Close the hard fd to /dev/ttypXXX, and re-open through
+        * the indirect /dev/tty interface.
+        */
+       close(t);
+       if ((t = open("/dev/tty", O_RDWR)) < 0)
+               fatalperror(net, "open(/dev/tty)");
+#  endif
+# else
+       /*
+        * We get our controlling tty assigned as a side-effect
+        * of opening up a tty device.  But on BSD based systems,
+        * this only happens if our process group is zero.  The
+        * setsid() call above may have set our pgrp, so clear
+        * it out before opening the tty...
+        */
+#  ifndef SOLARIS
+       (void) setpgrp(0, 0);
+#  else
+       (void) setpgrp();
+#  endif
+       close(open(line, O_RDWR));
+# endif
+       if (t != 0)
+               (void) dup2(t, 0);
+       if (t != 1)
+               (void) dup2(t, 1);
+       if (t != 2)
+               (void) dup2(t, 2);
+       if (t > 2)
+               close(t);
+       return(0);
+}
+#endif /* BSD <= 43 */
+
+#ifdef NEWINIT
+char *gen_id = "fe";
+#endif
+
+/*
+ * startslave(host)
+ *
+ * Given a hostname, do whatever
+ * is necessary to startup the login process on the slave side of the pty.
+ */
+
+/* ARGSUSED */
+       void
+startslave(host, autologin, autoname)
+       char *host;
+       int autologin;
+       char *autoname;
+{
+       register int i;
+       long time();
+       char name[256];
+#ifdef NEWINIT
+       extern char *ptyip;
+       struct init_request request;
+       void nologinproc();
+       register int n;
+#endif /* NEWINIT */
+
+#if    defined(AUTHENTICATION)
+       if (!autoname || !autoname[0])
+               autologin = 0;
+
+       if (autologin < auth_level) {
+               fatal(net, "Authorization failed");
+               exit(1);
+       }
+#endif
+
+#ifndef        NEWINIT
+# ifdef        PARENT_DOES_UTMP
+       utmp_sig_init();
+# endif        /* PARENT_DOES_UTMP */
+
+       if ((i = fork()) < 0)
+               fatalperror(net, "fork");
+       if (i) {
+# ifdef PARENT_DOES_UTMP
+               /*
+                * Cray parent will create utmp entry for child and send
+                * signal to child to tell when done.  Child waits for signal
+                * before doing anything important.
+                */
+               register int pid = i;
+               void sigjob P((int));
+
+               setpgrp();
+               utmp_sig_reset();               /* reset handler to default */
+               /*
+                * Create utmp entry for child
+                */
+               (void) time(&wtmp.ut_time);
+               wtmp.ut_type = LOGIN_PROCESS;
+               wtmp.ut_pid = pid;
+               SCPYN(wtmp.ut_user, "LOGIN");
+               SCPYN(wtmp.ut_host, host);
+               SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
+#ifndef        __hpux
+               SCPYN(wtmp.ut_id, wtmp.ut_line+3);
+#else
+               SCPYN(wtmp.ut_id, wtmp.ut_line+7);
+#endif
+               pututline(&wtmp);
+               endutent();
+               if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
+                       (void) write(i, (char *)&wtmp, sizeof(struct utmp));
+                       (void) close(i);
+               }
+#ifdef CRAY
+               (void) signal(WJSIGNAL, sigjob);
+#endif
+               utmp_sig_notify(pid);
+# endif        /* PARENT_DOES_UTMP */
+       } else {
+               getptyslave(autologin);
+               start_login(host, autologin, autoname);
+               /*NOTREACHED*/
+       }
+#else  /* NEWINIT */
+
+       /*
+        * Init will start up login process if we ask nicely.  We only wait
+        * for it to start up and begin normal telnet operation.
+        */
+       if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
+               char tbuf[128];
+               (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
+               fatalperror(net, tbuf);
+       }
+       memset((char *)&request, 0, sizeof(request));
+       request.magic = INIT_MAGIC;
+       SCPYN(request.gen_id, gen_id);
+       SCPYN(request.tty_id, &line[8]);
+       SCPYN(request.host, host);
+       SCPYN(request.term_type, terminaltype ? terminaltype : "network");
+#if    !defined(UNICOS5)
+       request.signal = SIGCLD;
+       request.pid = getpid();
+#endif
+#ifdef BFTPDAEMON
+       /*
+        * Are we working as the bftp daemon?
+        */
+       if (bftpd) {
+               SCPYN(request.exec_name, BFTPPATH);
+       }
+#endif /* BFTPDAEMON */
+       if (write(i, (char *)&request, sizeof(request)) < 0) {
+               char tbuf[128];
+               (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
+               fatalperror(net, tbuf);
+       }
+       (void) close(i);
+       (void) signal(SIGALRM, nologinproc);
+       for (i = 0; ; i++) {
+               char tbuf[128];
+               alarm(15);
+               n = read(pty, ptyip, BUFSIZ);
+               if (i == 3 || n >= 0 || !gotalarm)
+                       break;
+               gotalarm = 0;
+               sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
+               (void) write(net, tbuf, strlen(tbuf));
+       }
+       if (n < 0 && gotalarm)
+               fatal(net, "/etc/init didn't start login process");
+       pcc += n;
+       alarm(0);
+       (void) signal(SIGALRM, SIG_DFL);
+
+       return;
+#endif /* NEWINIT */
+}
+
+char   *envinit[3];
+extern char **environ;
+
+       void
+init_env()
+{
+       extern char *getenv();
+       char **envp;
+
+       envp = envinit;
+       if (*envp = getenv("TZ"))
+               *envp++ -= 3;
+#if    defined(CRAY) || defined(__hpux)
+       else
+               *envp++ = "TZ=GMT0";
+#endif
+       *envp = 0;
+       environ = envinit;
+}
+
+#ifndef        NEWINIT
+
+/*
+ * start_login(host)
+ *
+ * Assuming that we are now running as a child processes, this
+ * function will turn us into the login process.
+ */
+
+       void
+start_login(host, autologin, name)
+       char *host;
+       int autologin;
+       char *name;
+{
+       register char *cp;
+       register char **argv;
+       char **addarg();
+       extern char *getenv();
+#ifdef UTMPX
+       register int pid = getpid();
+       struct utmpx utmpx;
+#endif
+#ifdef SOLARIS
+       char *term;
+       char termbuf[64];
+#endif
+
+#ifdef UTMPX
+       /*
+        * Create utmp entry for child
+        */
+
+       memset(&utmpx, 0, sizeof(utmpx));
+       SCPYN(utmpx.ut_user, ".telnet");
+       SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
+       utmpx.ut_pid = pid;
+       utmpx.ut_id[0] = 't';
+       utmpx.ut_id[1] = 'n';
+       utmpx.ut_id[2] = SC_WILDC;
+       utmpx.ut_id[3] = SC_WILDC;
+       utmpx.ut_type = LOGIN_PROCESS;
+       (void) time(&utmpx.ut_tv.tv_sec);
+       if (pututxline(&utmpx) == NULL)
+               fatal(net, "pututxline failed");
+#endif
+
+       /*
+        * -h : pass on name of host.
+        *              WARNING:  -h is accepted by login if and only if
+        *                      getuid() == 0.
+        * -p : don't clobber the environment (so terminal type stays set).
+        *
+        * -f : force this login, he has already been authenticated
+        */
+       argv = addarg(0, "login");
+
+#if    !defined(NO_LOGIN_H)
+
+# if   defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       /*
+        * Don't add the "-h host" option if we are going
+        * to be adding the "-r host" option down below...
+        */
+       if ((auth_level < 0) || (autologin != AUTH_VALID))
+# endif
+       {
+               argv = addarg(argv, "-h");
+               argv = addarg(argv, host);
+#ifdef SOLARIS
+               /*
+                * SVR4 version of -h takes TERM= as second arg, or -
+                */
+               term = getenv("TERM");
+               if (term == NULL || term[0] == 0) {
+                       term = "-";
+               } else {
+                       strcpy(termbuf, "TERM=");
+                       strncat(termbuf, term, sizeof(termbuf) - 6);
+                       term = termbuf;
+               }
+               argv = addarg(argv, term);
+#endif
+       }
+#endif
+#if    !defined(NO_LOGIN_P)
+       argv = addarg(argv, "-p");
+#endif
+#ifdef LINEMODE
+       /*
+        * Set the environment variable "LINEMODE" to either
+        * "real" or "kludge" if we are operating in either
+        * real or kludge linemode.
+        */
+       if (lmodetype == REAL_LINEMODE)
+               setenv("LINEMODE", "real", 1);
+# ifdef KLUDGELINEMODE
+       else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
+               setenv("LINEMODE", "kludge", 1);
+# endif
+#endif
+#ifdef BFTPDAEMON
+       /*
+        * Are we working as the bftp daemon?  If so, then ask login
+        * to start bftp instead of shell.
+        */
+       if (bftpd) {
+               argv = addarg(argv, "-e");
+               argv = addarg(argv, BFTPPATH);
+       } else
+#endif
+#if    defined (SecurID)
+       /*
+        * don't worry about the -f that might get sent.
+        * A -s is supposed to override it anyhow.
+        */
+       if (require_SecurID)
+               argv = addarg(argv, "-s");
+#endif
+#if    defined (AUTHENTICATION)
+       if (auth_level >= 0 && autologin == AUTH_VALID) {
+# if   !defined(NO_LOGIN_F)
+               argv = addarg(argv, "-f");
+               argv = addarg(argv, name);
+# else
+#  if defined(LOGIN_R)
+               /*
+                * We don't have support for "login -f", but we
+                * can fool /bin/login into thinking that we are
+                * rlogind, and allow us to log in without a
+                * password.  The rlogin protocol expects
+                *      local-user\0remote-user\0term/speed\0
+                */
+
+               if (pty > 2) {
+                       register char *cp;
+                       char speed[128];
+                       int isecho, israw, xpty, len;
+                       extern int def_rspeed;
+#  ifndef LOGIN_HOST
+                       /*
+                        * Tell login that we are coming from "localhost".
+                        * If we passed in the real host name, then the
+                        * user would have to allow .rhost access from
+                        * every machine that they want authenticated
+                        * access to work from, which sort of defeats
+                        * the purpose of an authenticated login...
+                        * So, we tell login that the session is coming
+                        * from "localhost", and the user will only have
+                        * to have "localhost" in their .rhost file.
+                        */
+#                      define LOGIN_HOST "localhost"
+#  endif
+                       argv = addarg(argv, "-r");
+                       argv = addarg(argv, LOGIN_HOST);
+
+                       xpty = pty;
+# ifndef  STREAMSPTY
+                       pty = 0;
+# else
+                       ttyfd = 0;
+# endif
+                       init_termbuf();
+                       isecho = tty_isecho();
+                       israw = tty_israw();
+                       if (isecho || !israw) {
+                               tty_setecho(0);         /* Turn off echo */
+                               tty_setraw(1);          /* Turn on raw */
+                               set_termbuf();
+                       }
+                       len = strlen(name)+1;
+                       write(xpty, name, len);
+                       write(xpty, name, len);
+                       sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",
+                               (def_rspeed > 0) ? def_rspeed : 9600);
+                       len = strlen(speed)+1;
+                       write(xpty, speed, len);
+
+                       if (isecho || !israw) {
+                               init_termbuf();
+                               tty_setecho(isecho);
+                               tty_setraw(israw);
+                               set_termbuf();
+                               if (!israw) {
+                                       /*
+                                        * Write a newline to ensure
+                                        * that login will be able to
+                                        * read the line...
+                                        */
+                                       write(xpty, "\n", 1);
+                               }
+                       }
+                       pty = xpty;
+               }
+#  else
+               argv = addarg(argv, name);
+#  endif
+# endif
+       } else
+#endif
+       if (getenv("USER")) {
+               argv = addarg(argv, getenv("USER"));
+#if    defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
+               {
+                       register char **cpp;
+                       for (cpp = environ; *cpp; cpp++)
+                               argv = addarg(argv, *cpp);
+               }
+#endif
+               /*
+                * Assume that login will set the USER variable
+                * correctly.  For SysV systems, this means that
+                * USER will no longer be set, just LOGNAME by
+                * login.  (The problem is that if the auto-login
+                * fails, and the user then specifies a different
+                * account name, he can get logged in with both
+                * LOGNAME and USER in his environment, but the
+                * USER value will be wrong.
+                */
+               unsetenv("USER");
+       }
+#ifdef SOLARIS
+       else {
+               char **p;
+
+               argv = addarg(argv, "");        /* no login name */
+               for (p = environ; *p; p++) {
+                       argv = addarg(argv, *p);
+               }
+       }
+#endif /* SOLARIS */
+#if    defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
+       if (pty > 2)
+               close(pty);
+#endif
+       closelog();
+       /*
+        * This sleep(1) is in here so that telnetd can
+        * finish up with the tty.  There's a race condition
+        * the login banner message gets lost...
+        */
+       sleep(1);
+       execv(_PATH_LOGIN, argv);
+
+       syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
+       fatalperror(net, _PATH_LOGIN);
+       /*NOTREACHED*/
+}
+
+       char **
+addarg(argv, val)
+       register char **argv;
+       register char *val;
+{
+       register char **cpp;
+
+       if (argv == NULL) {
+               /*
+                * 10 entries, a leading length, and a null
+                */
+               argv = (char **)malloc(sizeof(*argv) * 12);
+               if (argv == NULL)
+                       return(NULL);
+               *argv++ = (char *)10;
+               *argv = (char *)0;
+       }
+       for (cpp = argv; *cpp; cpp++)
+               ;
+       if (cpp == &argv[(int)argv[-1]]) {
+               --argv;
+               *argv = (char *)((int)(*argv) + 10);
+               argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
+               if (argv == NULL)
+                       return(NULL);
+               argv++;
+               cpp = &argv[(int)argv[-1] - 10];
+       }
+       *cpp++ = val;
+       *cpp = 0;
+       return(argv);
+}
+#endif /* NEWINIT */
+
+/*
+ * cleanup()
+ *
+ * This is the routine to call when we are all through, to
+ * clean up anything that needs to be cleaned up.
+ */
+       /* ARGSUSED */
+       void
+cleanup(sig)
+       int sig;
+{
+#ifndef        PARENT_DOES_UTMP
+# if (BSD > 43) || defined(convex)
+       char *p;
+
+       p = line + sizeof("/dev/") - 1;
+       if (logout(p))
+               logwtmp(p, "", "");
+       (void)chmod(line, 0666);
+       (void)chown(line, 0, 0);
+       *p = 'p';
+       (void)chmod(line, 0666);
+       (void)chown(line, 0, 0);
+       (void) shutdown(net, 2);
+       exit(1);
+# else
+       void rmut();
+
+       rmut();
+       vhangup();      /* XXX */
+       (void) shutdown(net, 2);
+       exit(1);
+# endif
+#else  /* PARENT_DOES_UTMP */
+# ifdef        NEWINIT
+       (void) shutdown(net, 2);
+       exit(1);
+# else /* NEWINIT */
+#  ifdef CRAY
+       static int incleanup = 0;
+       register int t;
+       int child_status; /* status of child process as returned by waitpid */
+       int flags = WNOHANG|WUNTRACED;
+
+       /*
+        * 1: Pick up the zombie, if we are being called
+        *    as the signal handler.
+        * 2: If we are a nested cleanup(), return.
+        * 3: Try to clean up TMPDIR.
+        * 4: Fill in utmp with shutdown of process.
+        * 5: Close down the network and pty connections.
+        * 6: Finish up the TMPDIR cleanup, if needed.
+        */
+       if (sig == SIGCHLD) {
+               while (waitpid(-1, &child_status, flags) > 0)
+                       ;       /* VOID */
+               /* Check if the child process was stopped
+                * rather than exited.  We want cleanup only if
+                * the child has died.
+                */
+               if (WIFSTOPPED(child_status)) {
+                       return;
+               }
+       }
+       t = sigblock(sigmask(SIGCHLD));
+       if (incleanup) {
+               sigsetmask(t);
+               return;
+       }
+       incleanup = 1;
+       sigsetmask(t);
+#ifdef UNICOS7x
+       if (secflag) {
+               /*
+                *      We need to set ourselves back to a null
+                *      label to clean up.
+                */
+
+               setulvl(sysv.sy_minlvl);
+               setucmp((long)0);
+       }
+#endif /* UNICOS7x */
+
+       t = cleantmp(&wtmp);
+       setutent();     /* just to make sure */
+#  endif /* CRAY */
+       rmut(line);
+       close(pty);
+       (void) shutdown(net, 2);
+#  ifdef CRAY
+       if (t == 0)
+               cleantmp(&wtmp);
+#  endif /* CRAY */
+       exit(1);
+# endif        /* NEWINT */
+#endif /* PARENT_DOES_UTMP */
+}
+
+#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
+/*
+ * _utmp_sig_rcv
+ * utmp_sig_init
+ * utmp_sig_wait
+ *     These three functions are used to coordinate the handling of
+ *     the utmp file between the server and the soon-to-be-login shell.
+ *     The server actually creates the utmp structure, the child calls
+ *     utmp_sig_wait(), until the server calls utmp_sig_notify() and
+ *     signals the future-login shell to proceed.
+ */
+static int caught=0;           /* NZ when signal intercepted */
+static void (*func)();         /* address of previous handler */
+
+       void
+_utmp_sig_rcv(sig)
+       int sig;
+{
+       caught = 1;
+       (void) signal(SIGUSR1, func);
+}
+
+       void
+utmp_sig_init()
+{
+       /*
+        * register signal handler for UTMP creation
+        */
+       if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
+               fatalperror(net, "telnetd/signal");
+}
+
+       void
+utmp_sig_reset()
+{
+       (void) signal(SIGUSR1, func);   /* reset handler to default */
+}
+
+# ifdef __hpux
+# define sigoff() /* do nothing */
+# define sigon() /* do nothing */
+# endif
+
+       void
+utmp_sig_wait()
+{
+       /*
+        * Wait for parent to write our utmp entry.
+        */
+       sigoff();
+       while (caught == 0) {
+               pause();        /* wait until we get a signal (sigon) */
+               sigoff();       /* turn off signals while we check caught */
+       }
+       sigon();                /* turn on signals again */
+}
+
+       void
+utmp_sig_notify(pid)
+{
+       kill(pid, SIGUSR1);
+}
+
+# ifdef CRAY
+static int gotsigjob = 0;
+
+       /*ARGSUSED*/
+       void
+sigjob(sig)
+       int sig;
+{
+       register int jid;
+       register struct jobtemp *jp;
+
+       while ((jid = waitjob(NULL)) != -1) {
+               if (jid == 0) {
+                       return;
+               }
+               gotsigjob++;
+               jobend(jid, NULL, NULL);
+       }
+}
+
+/*
+ *     jid_getutid:
+ *             called by jobend() before calling cleantmp()
+ *             to find the correct $TMPDIR to cleanup.
+ */
+
+       struct utmp *
+jid_getutid(jid)
+       int jid;
+{
+       struct utmp *cur = NULL;
+
+       setutent();     /* just to make sure */
+       while (cur = getutent()) {
+               if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
+                       return(cur);
+               }
+       }
+
+       return(0);
+}
+
+/*
+ * Clean up the TMPDIR that login created.
+ * The first time this is called we pick up the info
+ * from the utmp.  If the job has already gone away,
+ * then we'll clean up and be done.  If not, then
+ * when this is called the second time it will wait
+ * for the signal that the job is done.
+ */
+       int
+cleantmp(wtp)
+       register struct utmp *wtp;
+{
+       struct utmp *utp;
+       static int first = 1;
+       register int mask, omask, ret;
+       extern struct utmp *getutid P((const struct utmp *_Id));
+
+
+       mask = sigmask(WJSIGNAL);
+
+       if (first == 0) {
+               omask = sigblock(mask);
+               while (gotsigjob == 0)
+                       sigpause(omask);
+               return(1);
+       }
+       first = 0;
+       setutent();     /* just to make sure */
+
+       utp = getutid(wtp);
+       if (utp == 0) {
+               syslog(LOG_ERR, "Can't get /var/run/utmp entry to clean TMPDIR");
+               return(-1);
+       }
+       /*
+        * Nothing to clean up if the user shell was never started.
+        */
+       if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
+               return(1);
+
+       /*
+        * Block the WJSIGNAL while we are in jobend().
+        */
+       omask = sigblock(mask);
+       ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
+       sigsetmask(omask);
+       return(ret);
+}
+
+       int
+jobend(jid, path, user)
+       register int jid;
+       register char *path;
+       register char *user;
+{
+       static int saved_jid = 0;
+       static int pty_saved_jid = 0;
+       static char saved_path[sizeof(wtmp.ut_tpath)+1];
+       static char saved_user[sizeof(wtmp.ut_user)+1];
+
+       /*
+        * this little piece of code comes into play
+        * only when ptyreconnect is used to reconnect
+        * to an previous session.
+        *
+        * this is the only time when the
+        * "saved_jid != jid" code is executed.
+        */
+
+       if ( saved_jid && saved_jid != jid ) {
+               if (!path) {    /* called from signal handler */
+                       pty_saved_jid = jid;
+               } else {
+                       pty_saved_jid = saved_jid;
+               }
+       }
+
+       if (path) {
+               strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
+               strncpy(saved_user, user, sizeof(wtmp.ut_user));
+               saved_path[sizeof(saved_path)] = '\0';
+               saved_user[sizeof(saved_user)] = '\0';
+       }
+       if (saved_jid == 0) {
+               saved_jid = jid;
+               return(0);
+       }
+
+       /* if the jid has changed, get the correct entry from the utmp file */
+
+       if ( saved_jid != jid ) {
+               struct utmp *utp = NULL;
+               struct utmp *jid_getutid();
+
+               utp = jid_getutid(pty_saved_jid);
+
+               if (utp == 0) {
+                       syslog(LOG_ERR, "Can't get /var/run/utmp entry to clean TMPDIR");
+                       return(-1);
+               }
+
+               cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
+               return(1);
+       }
+
+       cleantmpdir(jid, saved_path, saved_user);
+       return(1);
+}
+
+/*
+ * Fork a child process to clean up the TMPDIR
+ */
+cleantmpdir(jid, tpath, user)
+       register int jid;
+       register char *tpath;
+       register char *user;
+{
+       switch(fork()) {
+       case -1:
+               syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
+                                                       tpath);
+               break;
+       case 0:
+               execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
+               syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
+                                                       tpath, CLEANTMPCMD);
+               exit(1);
+       default:
+               /*
+                * Forget about child.  We will exit, and
+                * /etc/init will pick it up.
+                */
+               break;
+       }
+}
+# endif /* CRAY */
+#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
+
+/*
+ * rmut()
+ *
+ * This is the function called by cleanup() to
+ * remove the utmp entry for this person.
+ */
+
+#ifdef UTMPX
+       void
+rmut()
+{
+       register f;
+       int found = 0;
+       struct utmp *u, *utmp;
+       int nutmp;
+       struct stat statbf;
+
+       struct utmpx *utxp, utmpx;
+
+       /*
+        * This updates the utmpx and utmp entries and make a wtmp/x entry
+        */
+
+       SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
+       utxp = getutxline(&utmpx);
+       if (utxp) {
+               utxp->ut_type = DEAD_PROCESS;
+               utxp->ut_exit.e_termination = 0;
+               utxp->ut_exit.e_exit = 0;
+               (void) time(&utmpx.ut_tv.tv_sec);
+               utmpx.ut_tv.tv_usec = 0;
+               modutx(utxp);
+       }
+       endutxent();
+}  /* end of rmut */
+#endif
+
+#if    !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
+       void
+rmut()
+{
+       register f;
+       int found = 0;
+       struct utmp *u, *utmp;
+       int nutmp;
+       struct stat statbf;
+
+       f = open(utmpf, O_RDWR);
+       if (f >= 0) {
+               (void) fstat(f, &statbf);
+               utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
+               if (!utmp)
+                       syslog(LOG_ERR, "utmp malloc failed");
+               if (statbf.st_size && utmp) {
+                       nutmp = read(f, (char *)utmp, (int)statbf.st_size);
+                       nutmp /= sizeof(struct utmp);
+
+                       for (u = utmp ; u < &utmp[nutmp] ; u++) {
+                               if (SCMPN(u->ut_line, line+5) ||
+                                   u->ut_name[0]==0)
+                                       continue;
+                               (void) lseek(f, ((long)u)-((long)utmp), L_SET);
+                               SCPYN(u->ut_name, "");
+                               SCPYN(u->ut_host, "");
+                               (void) time(&u->ut_time);
+                               (void) write(f, (char *)u, sizeof(wtmp));
+                               found++;
+                       }
+               }
+               (void) close(f);
+       }
+       if (found) {
+               f = open(wtmpf, O_WRONLY|O_APPEND);
+               if (f >= 0) {
+                       SCPYN(wtmp.ut_line, line+5);
+                       SCPYN(wtmp.ut_name, "");
+                       SCPYN(wtmp.ut_host, "");
+                       (void) time(&wtmp.ut_time);
+                       (void) write(f, (char *)&wtmp, sizeof(wtmp));
+                       (void) close(f);
+               }
+       }
+       (void) chmod(line, 0666);
+       (void) chown(line, 0, 0);
+       line[strlen("/dev/")] = 'p';
+       (void) chmod(line, 0666);
+       (void) chown(line, 0, 0);
+}  /* end of rmut */
+#endif /* CRAY */
+
+#ifdef __hpux
+rmut (line)
+char *line;
+{
+       struct utmp utmp;
+       struct utmp *utptr;
+       int fd;                 /* for /etc/wtmp */
+
+       utmp.ut_type = USER_PROCESS;
+       (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
+       (void) setutent();
+       utptr = getutid(&utmp);
+       /* write it out only if it exists */
+       if (utptr) {
+               utptr->ut_type = DEAD_PROCESS;
+               utptr->ut_time = time((long *) 0);
+               (void) pututline(utptr);
+               /* set wtmp entry if wtmp file exists */
+               if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
+                       (void) write(fd, utptr, sizeof(utmp));
+                       (void) close(fd);
+               }
+       }
+       (void) endutent();
+
+       (void) chmod(line, 0666);
+       (void) chown(line, 0, 0);
+       line[14] = line[13];
+       line[13] = line[12];
+       line[8] = 'm';
+       line[9] = '/';
+       line[10] = 'p';
+       line[11] = 't';
+       line[12] = 'y';
+       (void) chmod(line, 0666);
+       (void) chown(line, 0, 0);
+}
+#endif
diff --git a/telnetd.tproj/telnetd.8 b/telnetd.tproj/telnetd.8
new file mode 100644 (file)
index 0000000..f618385
--- /dev/null
@@ -0,0 +1,607 @@
+.\" Copyright (c) 1983, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)telnetd.8   8.4 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt TELNETD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm telnetd
+.Nd DARPA
+.Tn TELNET
+protocol server
+.Sh SYNOPSIS
+.Nm /usr/libexec/telnetd
+.Op Fl BUhlkns
+.Op Fl D Ar debugmode
+.Op Fl I Ns Ar initid
+.Op Fl S Ar tos
+.Op Fl X Ar authtype
+.Op Fl a Ar authmode
+.Op Fl edebug
+.Op Fl r Ns Ar lowpty-highpty
+.Op Fl u Ar len
+.Op Fl debug Op Ar port
+.Sh DESCRIPTION
+The
+.Nm telnetd
+command is a server which supports the
+.Tn DARPA
+standard
+.Tn TELNET
+virtual terminal protocol.
+.Nm Telnetd
+is normally invoked by the internet server (see
+.Xr inetd 8 )
+for requests to connect to the
+.Tn TELNET
+port as indicated by the
+.Pa /etc/services
+file (see
+.Xr services 5 ) .
+The
+.Fl debug
+option may be used to start up
+.Nm telnetd
+manually, instead of through
+.Xr inetd 8 .
+If started up this way, 
+.Ar port
+may be specified to run
+.Nm telnetd
+on an alternate
+.Tn TCP
+port number.
+.Pp
+The
+.Nm telnetd
+command accepts the following options:
+.Bl -tag -width "-a authmode"
+.It Fl a Ar authmode
+This option may be used for specifying what mode should
+be used for authentication.
+Note that this option is only useful if
+.Nm telnetd
+has been compiled with support for the
+.Dv AUTHENTICATION
+option.
+There are several valid values for
+.Ar authmode:
+.Bl -tag -width debug
+.It debug
+Turns on authentication debugging code.
+.It user
+Only allow connections when the remote user
+can provide valid authentication information
+to identify the remote user,
+and is allowed access to the specified account
+without providing a password.
+.It valid
+Only allow connections when the remote user
+can provide valid authentication information
+to identify the remote user.
+The
+.Xr login 1
+command will provide any additional user verification
+needed if the remote user is not allowed automatic
+access to the specified account.
+.It other
+Only allow connections that supply some authentication information.
+This option is currently not supported
+by any of the existing authentication mechanisms,
+and is thus the same as specifying
+.Fl a
+.Cm valid .
+.It none
+This is the default state.
+Authentication information is not required.
+If no or insufficient authentication information
+is provided, then the
+.Xr login 1
+program will provide the necessary user
+verification.
+.It off
+This disables the authentication code.
+All user verification will happen through the
+.Xr login 1
+program.
+.El
+.It Fl B
+Specifies bftp server mode.  In this mode,
+.Nm telnetd
+causes login to start a
+.Xr bftp 1
+session rather than the user's
+normal shell.  In bftp daemon mode normal
+logins are not supported, and it must be used
+on a port other than the normal
+.Tn TELNET
+port.
+.It Fl D Ar debugmode
+This option may be used for debugging purposes.
+This allows
+.Nm telnetd
+to print out debugging information
+to the connection, allowing the user to see what
+.Nm telnetd
+is doing.
+There are several possible values for 
+.Ar debugmode:
+.Bl -tag -width exercise
+.It Cm options
+Prints information about the negotiation of
+.Tn TELNET
+options.
+.It Cm report
+Prints the 
+.Cm options
+information, plus some additional information
+about what processing is going on.
+.It Cm netdata
+Displays the data stream received by
+.Nm telnetd.
+.It Cm ptydata
+Displays data written to the pty.
+.It Cm exercise
+Has not been implemented yet.
+.El
+.It Fl debug
+Enables debugging on each socket created by
+.Nm telnetd
+(see
+.Dv SO_DEBUG
+in
+.Xr socket 2 ) .
+.It Fl edebug
+If
+.Nm telnetd
+has been compiled with support for data encryption, then the
+.Fl edebug
+option may be used to enable encryption debugging code.
+.It Fl h
+Disables the printing of host-specific information before
+login has been completed.
+.It Fl I Ar initid
+This option is only applicable to
+.Tn UNICOS
+systems prior to 7.0.
+It specifies the
+.Dv ID
+from
+.Pa /etc/inittab
+to use when init starts login sessions.  The default
+.Dv ID
+is
+.Dv fe.
+.It Fl k
+This option is only useful if
+.Nm telnetd
+has been compiled with both linemode and kludge linemode
+support.  If the
+.Fl k
+option is specified, then if the remote client does not
+support the
+.Dv LINEMODE
+option, then
+.Nm telnetd
+will operate in character at a time mode.
+It will still support kludge linemode, but will only
+go into kludge linemode if the remote client requests
+it.
+(This is done by by the client sending
+.Dv DONT SUPPRESS-GO-AHEAD
+and
+.Dv DONT ECHO . )
+The
+.Fl k
+option is most useful when there are remote clients
+that do not support kludge linemode, but pass the heuristic
+(if they respond with
+.Dv WILL TIMING-MARK
+in response to a
+.Dv DO TIMING-MARK)
+for kludge linemode support.
+.It Fl l
+Specifies line mode.  Tries to force clients to use line-
+at-a-time mode.
+If the
+.Dv LINEMODE
+option is not supported, it will go
+into kludge linemode.
+.It Fl n
+Disable
+.Dv TCP
+keep-alives.  Normally
+.Nm telnetd
+enables the
+.Tn TCP
+keep-alive mechanism to probe connections that
+have been idle for some period of time to determine
+if the client is still there, so that idle connections
+from machines that have crashed or can no longer
+be reached may be cleaned up.
+.It Fl r Ar lowpty-highpty
+This option is only enabled when
+.Nm telnetd
+is compiled for
+.Dv UNICOS.
+It specifies an inclusive range of pseudo-terminal devices to
+use.  If the system has sysconf variable
+.Dv _SC_CRAY_NPTY
+configured, the default pty search range is 0 to
+.Dv _SC_CRAY_NPTY;
+otherwise, the default range is 0 to 128.  Either
+.Ar lowpty
+or
+.Ar highpty
+may be omitted to allow changing
+either end of the search range.  If
+.Ar lowpty
+is omitted, the - character is still required so that
+.Nm telnetd
+can differentiate
+.Ar highpty
+from
+.Ar lowpty .
+.It Fl s
+This option is only enabled if
+.Nm telnetd
+is compiled with support for
+.Tn SecurID
+cards.
+It causes the
+.Fl s
+option to be passed on to
+.Xr login 1 ,
+and thus is only useful if
+.Xr login 1
+supports the
+.Fl s
+flag to indicate that only
+.Tn SecurID
+validated logins are allowed, and is
+usually useful for controlling remote logins
+from outside of a firewall.
+.It Fl S Ar tos
+.It Fl u Ar len
+This option is used to specify the size of the field
+in the
+.Dv utmp
+structure that holds the remote host name.
+If the resolved host name is longer than
+.Ar len ,
+the dotted decimal value will be used instead.
+This allows hosts with very long host names that
+overflow this field to still be uniquely identified.
+Specifying
+.Fl u0
+indicates that only dotted decimal addresses
+should be put into the
+.Pa utmp
+file.
+.ne 1i
+.It Fl U
+This option causes
+.Nm telnetd
+to refuse connections from addresses that
+cannot be mapped back into a symbolic name
+via the
+.Xr gethostbyaddr 3
+routine.
+.It Fl X Ar authtype
+This option is only valid if
+.Nm telnetd
+has been built with support for the authentication option.
+It disables the use of
+.Ar authtype
+authentication, and
+can be used to temporarily disable
+a specific authentication type without having to recompile
+.Nm telnetd .
+.El
+.Pp
+.Nm Telnetd
+operates by allocating a pseudo-terminal device (see
+.Xr pty 4 )
+for a client, then creating a login process which has
+the slave side of the pseudo-terminal as 
+.Dv stdin ,
+.Dv stdout
+and
+.Dv stderr .
+.Nm Telnetd
+manipulates the master side of the pseudo-terminal,
+implementing the
+.Tn TELNET
+protocol and passing characters
+between the remote client and the login process.
+.Pp
+When a
+.Tn TELNET
+session is started up, 
+.Nm telnetd
+sends
+.Tn TELNET
+options to the client side indicating
+a willingness to do the
+following
+.Tn TELNET
+options, which are described in more detail below:
+.Bd -literal -offset indent
+DO AUTHENTICATION
+WILL ENCRYPT
+DO TERMINAL TYPE
+DO TSPEED
+DO XDISPLOC
+DO NEW-ENVIRON
+DO ENVIRON
+WILL SUPPRESS GO AHEAD
+DO ECHO
+DO LINEMODE
+DO NAWS
+WILL STATUS
+DO LFLOW
+DO TIMING-MARK
+.Ed
+.Pp
+The pseudo-terminal allocated to the client is configured
+to operate in \*(lqcooked\*(rq mode, and with
+.Dv XTABS and
+.Dv CRMOD
+enabled (see
+.Xr tty 4 ) .
+.Pp
+.Nm Telnetd
+has support for enabling locally the following
+.Tn TELNET
+options:
+.Bl -tag -width "DO AUTHENTICATION"
+.It "WILL ECHO"
+When the
+.Dv LINEMODE
+option is enabled, a
+.Dv WILL ECHO
+or
+.Dv WONT ECHO
+will be sent to the client to indicate the
+current state of terminal echoing.
+When terminal echo is not desired, a
+.Dv WILL ECHO
+is sent to indicate that
+.Tn telnetd
+will take care of echoing any data that needs to be
+echoed to the terminal, and then nothing is echoed.
+When terminal echo is desired, a
+.Dv WONT ECHO
+is sent to indicate that
+.Tn telnetd
+will not be doing any terminal echoing, so the
+client should do any terminal echoing that is needed.
+.It "WILL BINARY"
+Indicates that the client is willing to send a
+8 bits of data, rather than the normal 7 bits
+of the Network Virtual Terminal.
+.It "WILL SGA"
+Indicates that it will not be sending
+.Dv IAC GA,
+go ahead, commands.
+.It "WILL STATUS"
+Indicates a willingness to send the client, upon
+request, of the current status of all
+.Tn TELNET
+options.
+.It "WILL TIMING-MARK"
+Whenever a
+.Dv DO TIMING-MARK
+command is received, it is always responded
+to with a
+.Dv WILL TIMING-MARK
+.ne 1i
+.It "WILL LOGOUT"
+When a
+.Dv DO LOGOUT
+is received, a
+.Dv WILL LOGOUT
+is sent in response, and the
+.Tn TELNET
+session is shut down.
+.It "WILL ENCRYPT"
+Only sent if
+.Nm telnetd
+is compiled with support for data encryption, and
+indicates a willingness to decrypt
+the data stream.
+.El
+.Pp
+.Nm Telnetd
+has support for enabling remotely the following
+.Tn TELNET
+options:
+.Bl -tag -width "DO AUTHENTICATION"
+.It "DO BINARY"
+Sent to indicate that
+.Tn telnetd
+is willing to receive an 8 bit data stream.
+.It "DO LFLOW"
+Requests that the client handle flow control
+characters remotely.
+.It "DO ECHO"
+This is not really supported, but is sent to identify a 4.2BSD
+.Xr telnet 1
+client, which will improperly respond with
+.Dv WILL ECHO.
+If a
+.Dv WILL ECHO
+is received, a
+.Dv DONT ECHO
+will be sent in response.
+.It "DO TERMINAL-TYPE"
+Indicates a desire to be able to request the
+name of the type of terminal that is attached
+to the client side of the connection.
+.It "DO SGA"
+Indicates that it does not need to receive
+.Dv IAC GA,
+the go ahead command.
+.It "DO NAWS"
+Requests that the client inform the server when
+the window (display) size changes.
+.It "DO TERMINAL-SPEED"
+Indicates a desire to be able to request information
+about the speed of the serial line to which
+the client is attached.
+.It "DO XDISPLOC"
+Indicates a desire to be able to request the name
+of the X windows display that is associated with
+the telnet client.
+.It "DO NEW-ENVIRON"
+Indicates a desire to be able to request environment
+variable information, as described in RFC 1572.
+.It "DO ENVIRON"
+Indicates a desire to be able to request environment
+variable information, as described in RFC 1408.
+.It "DO LINEMODE"
+Only sent if
+.Nm telnetd
+is compiled with support for linemode, and
+requests that the client do line by line processing.
+.It "DO TIMING-MARK"
+Only sent if
+.Nm telnetd
+is compiled with support for both linemode and
+kludge linemode, and the client responded with
+.Dv WONT LINEMODE.
+If the client responds with
+.Dv WILL TM,
+the it is assumed that the client supports
+kludge linemode.
+Note that the
+.Op Fl k
+option can be used to disable this.
+.It "DO AUTHENTICATION"
+Only sent if
+.Nm telnetd
+is compiled with support for authentication, and
+indicates a willingness to receive authentication
+information for automatic login.
+.It "DO ENCRYPT"
+Only sent if
+.Nm telnetd
+is compiled with support for data encryption, and
+indicates a willingness to decrypt
+the data stream.
+.Sh ENVIRONMENT
+.Sh FILES
+.Pa /etc/services
+.br
+.Pa /etc/inittab
+(UNICOS systems only)
+.br
+.Pa /etc/iptos
+(if supported)
+.br
+.Pa /usr/ucb/bftp
+(if supported)
+.Sh "SEE ALSO"
+.Xr telnet 1 ,
+.Xr login 1 ,
+.Xr bftp 1
+(if supported)
+.Sh STANDARDS
+.Bl -tag -compact -width RFC-1572
+.It Cm RFC-854
+.Tn TELNET
+PROTOCOL SPECIFICATION
+.It Cm RFC-855
+TELNET OPTION SPECIFICATIONS
+.It Cm RFC-856
+TELNET BINARY TRANSMISSION
+.It Cm RFC-857
+TELNET ECHO OPTION
+.It Cm RFC-858
+TELNET SUPPRESS GO AHEAD OPTION
+.It Cm RFC-859
+TELNET STATUS OPTION
+.It Cm RFC-860
+TELNET TIMING MARK OPTION
+.It Cm RFC-861
+TELNET EXTENDED OPTIONS - LIST OPTION
+.It Cm RFC-885
+TELNET END OF RECORD OPTION
+.It Cm RFC-1073
+Telnet Window Size Option
+.It Cm RFC-1079
+Telnet Terminal Speed Option
+.It Cm RFC-1091
+Telnet Terminal-Type Option
+.It Cm RFC-1096
+Telnet X Display Location Option
+.It Cm RFC-1123
+Requirements for Internet Hosts -- Application and Support
+.It Cm RFC-1184
+Telnet Linemode Option
+.It Cm RFC-1372
+Telnet Remote Flow Control Option
+.It Cm RFC-1416
+Telnet Authentication Option
+.It Cm RFC-1411
+Telnet Authentication: Kerberos Version 4
+.It Cm RFC-1412
+Telnet Authentication: SPX
+.It Cm RFC-1571
+Telnet Environment Option Interoperability Issues
+.It Cm RFC-1572
+Telnet Environment Option
+.Sh BUGS
+Some
+.Tn TELNET
+commands are only partially implemented.
+.Pp
+Because of bugs in the original 4.2 BSD
+.Xr telnet 1 ,
+.Nm telnetd
+performs some dubious protocol exchanges to try to discover if the remote
+client is, in fact, a 4.2 BSD
+.Xr telnet 1 .
+.Pp
+Binary mode
+has no common interpretation except between similar operating systems
+(Unix in this case).
+.Pp
+The terminal type name received from the remote client is converted to
+lower case.
+.Pp
+.Nm Telnetd
+never sends
+.Tn TELNET
+.Dv IAC GA
+(go ahead) commands.
diff --git a/telnetd.tproj/telnetd.c b/telnetd.tproj/telnetd.c
new file mode 100644 (file)
index 0000000..01943a4
--- /dev/null
@@ -0,0 +1,1640 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)telnetd.c  8.4 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include "telnetd.h"
+#include "pathnames.h"
+
+#if    defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY)
+/*
+ * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can
+ * use it to tell us to turn off all the socket security code,
+ * since that is only used in UNICOS 7.0 and later.
+ */
+# undef _SC_CRAY_SECURE_SYS
+#endif
+
+#if    defined(_SC_CRAY_SECURE_SYS)
+#include <sys/sysv.h>
+#include <sys/secdev.h>
+# ifdef SO_SEC_MULTI           /* 8.0 code */
+#include <sys/secparm.h>
+#include <sys/usrv.h>
+# endif /* SO_SEC_MULTI */
+int    secflag;
+char   tty_dev[16];
+struct secdev dv;
+struct sysv sysv;
+# ifdef SO_SEC_MULTI           /* 8.0 code */
+struct socksec ss;
+# else /* SO_SEC_MULTI */      /* 7.0 code */
+struct socket_security ss;
+# endif /* SO_SEC_MULTI */
+#endif /* _SC_CRAY_SECURE_SYS */
+
+#if    defined(AUTHENTICATION)
+#include <libtelnet/auth.h>
+int    auth_level = 0;
+#endif
+#if    defined(SecurID)
+int    require_SecurID = 0;
+#endif
+
+extern int utmp_len;
+int    registerd_host_only = 0;
+
+#ifdef STREAMSPTY
+# include <stropts.h>
+# include <termio.h>
+/* make sure we don't get the bsd version */
+# include "/usr/include/sys/tty.h"
+# include <sys/ptyvar.h>
+
+/*
+ * Because of the way ptyibuf is used with streams messages, we need
+ * ptyibuf+1 to be on a full-word boundary.  The following wierdness
+ * is simply to make that happen.
+ */
+long   ptyibufbuf[BUFSIZ/sizeof(long)+1];
+char   *ptyibuf = ((char *)&ptyibufbuf[1])-1;
+char   *ptyip = ((char *)&ptyibufbuf[1])-1;
+char   ptyibuf2[BUFSIZ];
+unsigned char ctlbuf[BUFSIZ];
+struct strbuf strbufc, strbufd;
+
+int readstream();
+
+#else  /* ! STREAMPTY */
+
+/*
+ * I/O data buffers,
+ * pointers, and counters.
+ */
+char   ptyibuf[BUFSIZ], *ptyip = ptyibuf;
+char   ptyibuf2[BUFSIZ];
+
+#endif /* ! STREAMPTY */
+
+int    hostinfo = 1;                   /* do we print login banner? */
+
+#ifdef CRAY
+extern int      newmap; /* nonzero if \n maps to ^M^J */
+int    lowpty = 0, highpty;    /* low, high pty numbers */
+#endif /* CRAY */
+
+int debug = 0;
+int keepalive = 1;
+char *progname;
+
+extern void usage P((void));
+void doit(struct sockaddr_in *);
+int terminaltypeok(char *);
+void startslave(char *, int, char *);
+
+
+/*
+ * The string to pass to getopt().  We do it this way so
+ * that only the actual options that we support will be
+ * passed off to getopt().
+ */
+char valid_opts[] = {
+       'd', ':', 'h', 'k', 'n', 'S', ':', 'u', ':', 'U',
+#ifdef AUTHENTICATION
+       'a', ':', 'X', ':',
+#endif
+#ifdef BFTPDAEMON
+       'B',
+#endif
+#ifdef DIAGNOSTICS
+       'D', ':',
+#endif
+#ifdef ENCRYPTION
+       'e', ':',
+#endif
+#if    defined(CRAY) && defined(NEWINIT)
+       'I', ':',
+#endif
+#ifdef LINEMODE
+       'l',
+#endif
+#ifdef CRAY
+       'r', ':',
+#endif
+#ifdef SecurID
+       's',
+#endif
+       '\0'
+};
+
+int
+main(argc, argv)
+       char *argv[];
+{
+       struct sockaddr_in from;
+       int on = 1, fromlen;
+       register int ch;
+       extern char *optarg;
+       extern int optind;
+#if    defined(IPPROTO_IP) && defined(IP_TOS)
+       int tos = -1;
+#endif
+
+       pfrontp = pbackp = ptyobuf;
+       netip = netibuf;
+       nfrontp = nbackp = netobuf;
+#ifdef ENCRYPTION
+       nclearto = 0;
+#endif /* ENCRYPTION */
+
+       progname = *argv;
+
+#ifdef CRAY
+       /*
+        * Get number of pty's before trying to process options,
+        * which may include changing pty range.
+        */
+       highpty = getnpty();
+#endif /* CRAY */
+
+       while ((ch = getopt(argc, argv, valid_opts)) != EOF) {
+               switch(ch) {
+
+#ifdef AUTHENTICATION
+               case 'a':
+                       /*
+                        * Check for required authentication level
+                        */
+                       if (strcmp(optarg, "debug") == 0) {
+                               extern int auth_debug_mode;
+                               auth_debug_mode = 1;
+                       } else if (strcasecmp(optarg, "none") == 0) {
+                               auth_level = 0;
+                       } else if (strcasecmp(optarg, "other") == 0) {
+                               auth_level = AUTH_OTHER;
+                       } else if (strcasecmp(optarg, "user") == 0) {
+                               auth_level = AUTH_USER;
+                       } else if (strcasecmp(optarg, "valid") == 0) {
+                               auth_level = AUTH_VALID;
+                       } else if (strcasecmp(optarg, "off") == 0) {
+                               /*
+                                * This hack turns off authentication
+                                */
+                               auth_level = -1;
+                       } else {
+                               fprintf(stderr,
+                           "telnetd: unknown authorization level for -a\n");
+                       }
+                       break;
+#endif /* AUTHENTICATION */
+
+#ifdef BFTPDAEMON
+               case 'B':
+                       bftpd++;
+                       break;
+#endif /* BFTPDAEMON */
+
+               case 'd':
+                       if (strcmp(optarg, "ebug") == 0) {
+                               debug++;
+                               break;
+                       }
+                       usage();
+                       /* NOTREACHED */
+                       break;
+
+#ifdef DIAGNOSTICS
+               case 'D':
+                       /*
+                        * Check for desired diagnostics capabilities.
+                        */
+                       if (!strcmp(optarg, "report")) {
+                               diagnostic |= TD_REPORT|TD_OPTIONS;
+                       } else if (!strcmp(optarg, "exercise")) {
+                               diagnostic |= TD_EXERCISE;
+                       } else if (!strcmp(optarg, "netdata")) {
+                               diagnostic |= TD_NETDATA;
+                       } else if (!strcmp(optarg, "ptydata")) {
+                               diagnostic |= TD_PTYDATA;
+                       } else if (!strcmp(optarg, "options")) {
+                               diagnostic |= TD_OPTIONS;
+                       } else {
+                               usage();
+                               /* NOT REACHED */
+                       }
+                       break;
+#endif /* DIAGNOSTICS */
+
+#ifdef ENCRYPTION
+               case 'e':
+                       if (strcmp(optarg, "debug") == 0) {
+                               extern int encrypt_debug_mode;
+                               encrypt_debug_mode = 1;
+                               break;
+                       }
+                       usage();
+                       /* NOTREACHED */
+                       break;
+#endif /* ENCRYPTION */
+
+               case 'h':
+                       hostinfo = 0;
+                       break;
+
+#if    defined(CRAY) && defined(NEWINIT)
+               case 'I':
+                   {
+                       extern char *gen_id;
+                       gen_id = optarg;
+                       break;
+                   }
+#endif /* defined(CRAY) && defined(NEWINIT) */
+
+#ifdef LINEMODE
+               case 'l':
+                       alwayslinemode = 1;
+                       break;
+#endif /* LINEMODE */
+
+               case 'k':
+#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
+                       lmodetype = NO_AUTOKLUDGE;
+#else
+                       /* ignore -k option if built without kludge linemode */
+#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+                       break;
+
+               case 'n':
+                       keepalive = 0;
+                       break;
+
+#ifdef CRAY
+               case 'r':
+                   {
+                       char *strchr();
+                       char *c;
+
+                       /*
+                        * Allow the specification of alterations
+                        * to the pty search range.  It is legal to
+                        * specify only one, and not change the
+                        * other from its default.
+                        */
+                       c = strchr(optarg, '-');
+                       if (c) {
+                               *c++ = '\0';
+                               highpty = atoi(c);
+                       }
+                       if (*optarg != '\0')
+                               lowpty = atoi(optarg);
+                       if ((lowpty > highpty) || (lowpty < 0) ||
+                                                       (highpty > 32767)) {
+                               usage();
+                               /* NOT REACHED */
+                       }
+                       break;
+                   }
+#endif /* CRAY */
+
+#ifdef SecurID
+               case 's':
+                       /* SecurID required */
+                       require_SecurID = 1;
+                       break;
+#endif /* SecurID */
+               case 'S':
+#ifdef HAS_GETTOS
+                       if ((tos = parsetos(optarg, "tcp")) < 0)
+                               fprintf(stderr, "%s%s%s\n",
+                                       "telnetd: Bad TOS argument '", optarg,
+                                       "'; will try to use default TOS");
+#else
+                       fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
+                                               "-S flag not supported\n");
+#endif
+                       break;
+
+               case 'u':
+                       utmp_len = atoi(optarg);
+                       break;
+
+               case 'U':
+                       registerd_host_only = 1;
+                       break;
+
+#ifdef AUTHENTICATION
+               case 'X':
+                       /*
+                        * Check for invalid authentication types
+                        */
+                       auth_disable_name(optarg);
+                       break;
+#endif /* AUTHENTICATION */
+
+               default:
+                       fprintf(stderr, "telnetd: %c: unknown option\n", ch);
+                       /* FALLTHROUGH */
+               case '?':
+                       usage();
+                       /* NOTREACHED */
+               }
+       }
+
+       argc -= optind;
+       argv += optind;
+
+       if (debug) {
+           int s, ns, foo;
+           struct servent *sp;
+           static struct sockaddr_in sin = { AF_INET };
+
+           if (argc > 1) {
+               usage();
+               /* NOT REACHED */
+           } else if (argc == 1) {
+                   if (sp = getservbyname(*argv, "tcp")) {
+                       sin.sin_port = sp->s_port;
+                   } else {
+                       sin.sin_port = atoi(*argv);
+                       if ((int)sin.sin_port <= 0) {
+                           fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
+                           usage();
+                           /* NOT REACHED */
+                       }
+                       sin.sin_port = htons((u_short)sin.sin_port);
+                  }
+           } else {
+               sp = getservbyname("telnet", "tcp");
+               if (sp == 0) {
+                   fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
+                   exit(1);
+               }
+               sin.sin_port = sp->s_port;
+           }
+
+           s = socket(AF_INET, SOCK_STREAM, 0);
+           if (s < 0) {
+                   perror("telnetd: socket");;
+                   exit(1);
+           }
+           (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                               (char *)&on, sizeof(on));
+           if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
+               perror("bind");
+               exit(1);
+           }
+           if (listen(s, 1) < 0) {
+               perror("listen");
+               exit(1);
+           }
+           foo = sizeof sin;
+           ns = accept(s, (struct sockaddr *)&sin, &foo);
+           if (ns < 0) {
+               perror("accept");
+               exit(1);
+           }
+           (void) dup2(ns, 0);
+           (void) close(ns);
+           (void) close(s);
+#ifdef convex
+       } else if (argc == 1) {
+               ; /* VOID*/             /* Just ignore the host/port name */
+#endif
+       } else if (argc > 0) {
+               usage();
+               /* NOT REACHED */
+       }
+
+#if    defined(_SC_CRAY_SECURE_SYS)
+       secflag = sysconf(_SC_CRAY_SECURE_SYS);
+
+       /*
+        *      Get socket's security label
+        */
+       if (secflag)  {
+               int szss = sizeof(ss);
+#ifdef SO_SEC_MULTI                    /* 8.0 code */
+               int sock_multi;
+               int szi = sizeof(int);
+#endif /* SO_SEC_MULTI */
+
+               memset((char *)&dv, 0, sizeof(dv));
+
+               if (getsysv(&sysv, sizeof(struct sysv)) != 0) {
+                       perror("getsysv");
+                       exit(1);
+               }
+
+               /*
+                *      Get socket security label and set device values
+                *         {security label to be set on ttyp device}
+                */
+#ifdef SO_SEC_MULTI                    /* 8.0 code */
+               if ((getsockopt(0, SOL_SOCKET, SO_SECURITY,
+                              (char *)&ss, &szss) < 0) ||
+                   (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI,
+                               (char *)&sock_multi, &szi) < 0)) {
+                       perror("getsockopt");
+                       exit(1);
+               } else {
+                       dv.dv_actlvl = ss.ss_actlabel.lt_level;
+                       dv.dv_actcmp = ss.ss_actlabel.lt_compart;
+                       if (!sock_multi) {
+                               dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl;
+                               dv.dv_valcmp = dv.dv_actcmp;
+                       } else {
+                               dv.dv_minlvl = ss.ss_minlabel.lt_level;
+                               dv.dv_maxlvl = ss.ss_maxlabel.lt_level;
+                               dv.dv_valcmp = ss.ss_maxlabel.lt_compart;
+                       }
+                       dv.dv_devflg = 0;
+               }
+#else /* SO_SEC_MULTI */               /* 7.0 code */
+               if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
+                               (char *)&ss, &szss) >= 0) {
+                       dv.dv_actlvl = ss.ss_slevel;
+                       dv.dv_actcmp = ss.ss_compart;
+                       dv.dv_minlvl = ss.ss_minlvl;
+                       dv.dv_maxlvl = ss.ss_maxlvl;
+                       dv.dv_valcmp = ss.ss_maxcmp;
+               }
+#endif /* SO_SEC_MULTI */
+       }
+#endif /* _SC_CRAY_SECURE_SYS */
+
+       openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+       fromlen = sizeof (from);
+       if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+               fprintf(stderr, "%s: ", progname);
+               perror("getpeername");
+               _exit(1);
+       }
+       if (keepalive &&
+           setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
+                       (char *)&on, sizeof (on)) < 0) {
+               syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+       }
+
+#if    defined(IPPROTO_IP) && defined(IP_TOS)
+       {
+# if   defined(HAS_GETTOS)
+               struct tosent *tp;
+               if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+                       tos = tp->t_tos;
+# endif
+               if (tos < 0)
+                       tos = 020;      /* Low Delay bit */
+               if (tos
+                  && (setsockopt(0, IPPROTO_IP, IP_TOS,
+                                 (char *)&tos, sizeof(tos)) < 0)
+                  && (errno != ENOPROTOOPT) )
+                       syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+       }
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+       net = 0;
+       doit(&from);
+       /* NOTREACHED */
+       exit(0);
+}  /* end of main */
+
+       void
+usage()
+{
+       fprintf(stderr, "Usage: telnetd");
+#ifdef AUTHENTICATION
+       fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t");
+#endif
+#ifdef BFTPDAEMON
+       fprintf(stderr, " [-B]");
+#endif
+       fprintf(stderr, " [-debug]");
+#ifdef DIAGNOSTICS
+       fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
+#endif
+#ifdef AUTHENTICATION
+       fprintf(stderr, " [-edebug]");
+#endif
+       fprintf(stderr, " [-h]");
+#if    defined(CRAY) && defined(NEWINIT)
+       fprintf(stderr, " [-Iinitid]");
+#endif
+#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
+       fprintf(stderr, " [-k]");
+#endif
+#ifdef LINEMODE
+       fprintf(stderr, " [-l]");
+#endif
+       fprintf(stderr, " [-n]");
+#ifdef CRAY
+       fprintf(stderr, " [-r[lowpty]-[highpty]]");
+#endif
+       fprintf(stderr, "\n\t");
+#ifdef SecurID
+       fprintf(stderr, " [-s]");
+#endif
+#ifdef HAS_GETTOS
+       fprintf(stderr, " [-S tos]");
+#endif
+#ifdef AUTHENTICATION
+       fprintf(stderr, " [-X auth-type]");
+#endif
+       fprintf(stderr, " [-u utmp_hostname_length] [-U]");
+       fprintf(stderr, " [port]\n");
+       exit(1);
+}
+
+/*
+ * getterminaltype
+ *
+ *     Ask the other end to send along its terminal type and speed.
+ * Output is the variable terminaltype filled in.
+ */
+static unsigned char ttytype_sbbuf[] = {
+       IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
+};
+
+    int
+getterminaltype(name)
+    char *name;
+{
+    int retval = -1;
+    void _gettermname();
+
+    settimer(baseline);
+#if    defined(AUTHENTICATION)
+    /*
+     * Handle the Authentication option before we do anything else.
+     */
+    send_do(TELOPT_AUTHENTICATION, 1);
+    while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
+       ttloop();
+    if (his_state_is_will(TELOPT_AUTHENTICATION)) {
+       retval = auth_wait(name);
+    }
+#endif
+
+#ifdef ENCRYPTION
+    send_will(TELOPT_ENCRYPT, 1);
+#endif /* ENCRYPTION */
+    send_do(TELOPT_TTYPE, 1);
+    send_do(TELOPT_TSPEED, 1);
+    send_do(TELOPT_XDISPLOC, 1);
+    send_do(TELOPT_NEW_ENVIRON, 1);
+    send_do(TELOPT_OLD_ENVIRON, 1);
+    while (
+#ifdef ENCRYPTION
+          his_do_dont_is_changing(TELOPT_ENCRYPT) ||
+#endif /* ENCRYPTION */
+          his_will_wont_is_changing(TELOPT_TTYPE) ||
+          his_will_wont_is_changing(TELOPT_TSPEED) ||
+          his_will_wont_is_changing(TELOPT_XDISPLOC) ||
+          his_will_wont_is_changing(TELOPT_NEW_ENVIRON) ||
+          his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) {
+       ttloop();
+    }
+#ifdef ENCRYPTION
+    /*
+     * Wait for the negotiation of what type of encryption we can
+     * send with.  If autoencrypt is not set, this will just return.
+     */
+    if (his_state_is_will(TELOPT_ENCRYPT)) {
+       encrypt_wait();
+    }
+#endif /* ENCRYPTION */
+    if (his_state_is_will(TELOPT_TSPEED)) {
+       static unsigned char sb[] =
+                       { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
+
+       memmove(nfrontp, sb, sizeof sb);
+       nfrontp += sizeof sb;
+       DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+    }
+    if (his_state_is_will(TELOPT_XDISPLOC)) {
+       static unsigned char sb[] =
+                       { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
+
+       memmove(nfrontp, sb, sizeof sb);
+       nfrontp += sizeof sb;
+       DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+    }
+    if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
+       static unsigned char sb[] =
+                       { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
+
+       memmove(nfrontp, sb, sizeof sb);
+       nfrontp += sizeof sb;
+       DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+    }
+    else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
+       static unsigned char sb[] =
+                       { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
+
+       memmove(nfrontp, sb, sizeof sb);
+       nfrontp += sizeof sb;
+       DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+    }
+    if (his_state_is_will(TELOPT_TTYPE)) {
+
+       memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
+       nfrontp += sizeof ttytype_sbbuf;
+       DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
+                                       sizeof ttytype_sbbuf - 2););
+    }
+    if (his_state_is_will(TELOPT_TSPEED)) {
+       while (sequenceIs(tspeedsubopt, baseline))
+           ttloop();
+    }
+    if (his_state_is_will(TELOPT_XDISPLOC)) {
+       while (sequenceIs(xdisplocsubopt, baseline))
+           ttloop();
+    }
+    if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
+       while (sequenceIs(environsubopt, baseline))
+           ttloop();
+    }
+    if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
+       while (sequenceIs(oenvironsubopt, baseline))
+           ttloop();
+    }
+    if (his_state_is_will(TELOPT_TTYPE)) {
+       char first[256], last[256];
+
+       while (sequenceIs(ttypesubopt, baseline))
+           ttloop();
+
+       /*
+        * If the other side has already disabled the option, then
+        * we have to just go with what we (might) have already gotten.
+        */
+       if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
+           (void) strncpy(first, terminaltype, sizeof(first));
+           for(;;) {
+               /*
+                * Save the unknown name, and request the next name.
+                */
+               (void) strncpy(last, terminaltype, sizeof(last));
+               _gettermname();
+               if (terminaltypeok(terminaltype))
+                   break;
+               if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
+                   his_state_is_wont(TELOPT_TTYPE)) {
+                   /*
+                    * We've hit the end.  If this is the same as
+                    * the first name, just go with it.
+                    */
+                   if (strncmp(first, terminaltype, sizeof(first)) == 0)
+                       break;
+                   /*
+                    * Get the terminal name one more time, so that
+                    * RFC1091 compliant telnets will cycle back to
+                    * the start of the list.
+                    */
+                    _gettermname();
+                   if (strncmp(first, terminaltype, sizeof(first)) != 0)
+                       (void) strncpy(terminaltype, first, sizeof(first));
+                   break;
+               }
+           }
+       }
+    }
+    return(retval);
+}  /* end of getterminaltype */
+
+    void
+_gettermname()
+{
+    /*
+     * If the client turned off the option,
+     * we can't send another request, so we
+     * just return.
+     */
+    if (his_state_is_wont(TELOPT_TTYPE))
+       return;
+    settimer(baseline);
+    memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
+    nfrontp += sizeof ttytype_sbbuf;
+    DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
+                                       sizeof ttytype_sbbuf - 2););
+    while (sequenceIs(ttypesubopt, baseline))
+       ttloop();
+}
+
+    int
+terminaltypeok(s)
+    char *s;
+{
+    char buf[1024];
+
+    if (terminaltype == NULL)
+       return(1);
+
+    /*
+     * tgetent() will return 1 if the type is known, and
+     * 0 if it is not known.  If it returns -1, it couldn't
+     * open the database.  But if we can't open the database,
+     * it won't help to say we failed, because we won't be
+     * able to verify anything else.  So, we treat -1 like 1.
+     */
+    if (tgetent(buf, s) == 0)
+       return(0);
+    return(1);
+}
+
+#ifndef        MAXHOSTNAMELEN
+#define        MAXHOSTNAMELEN 64
+#endif /* MAXHOSTNAMELEN */
+
+char *hostname;
+char host_name[MAXHOSTNAMELEN];
+char remote_host_name[MAXHOSTNAMELEN];
+
+#ifndef        convex
+extern void telnet P((int, int));
+#else
+extern void telnet P((int, int, char *));
+#endif
+
+/*
+ * Get a pty, scan input lines.
+ */
+void
+doit(who)
+       struct sockaddr_in *who;
+{
+       char *host = NULL, *inet_ntoa();
+       struct hostent *hp;
+       int level;
+       int ptynum;
+       char user_name[256];
+
+       /*
+        * Find an available pty to use.
+        */
+#ifndef        convex
+       pty = getpty(&ptynum);
+       if (pty < 0)
+               fatal(net, "All network ports in use");
+#else
+       for (;;) {
+               char *lp;
+               extern char *line, *getpty();
+
+               if ((lp = getpty()) == NULL)
+                       fatal(net, "Out of ptys");
+
+               if ((pty = open(lp, O_RDWR)) >= 0) {
+                       strncpy(line,lp, sizeof(line)-1);
+                       line[sizeof(line)-1] = '\0';
+                       line[5] = 't';
+                       break;
+               }
+       }
+#endif
+
+#if    defined(_SC_CRAY_SECURE_SYS)
+       /*
+        *      set ttyp line security label
+        */
+       if (secflag) {
+               char slave_dev[16];
+
+               sprintf(tty_dev, "/dev/pty/%03d", ptynum);
+               if (setdevs(tty_dev, &dv) < 0)
+                       fatal(net, "cannot set pty security");
+               sprintf(slave_dev, "/dev/ttyp%03d", ptynum);
+               if (setdevs(slave_dev, &dv) < 0)
+                       fatal(net, "cannot set tty security");
+       }
+#endif /* _SC_CRAY_SECURE_SYS */
+
+       /* get name of connected client */
+       hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
+               who->sin_family);
+
+       if (hp == NULL && registerd_host_only) {
+               fatal(net, "Couldn't resolve your address into a host name.\r\n\
+        Please contact your net administrator");
+       } else if (hp &&
+           (strlen(hp->h_name) <= (unsigned int)((utmp_len < 0) ? -utmp_len
+                                                                : utmp_len))) {
+               host = hp->h_name;
+       } else {
+               host = inet_ntoa(who->sin_addr);
+       }
+       /*
+        * We must make a copy because Kerberos is probably going
+        * to also do a gethost* and overwrite the static data...
+        */
+       strncpy(remote_host_name, host, sizeof(remote_host_name)-1);
+       remote_host_name[sizeof(remote_host_name)-1] = 0;
+       host = remote_host_name;
+
+       (void) gethostname(host_name, sizeof (host_name));
+       hostname = host_name;
+
+#if    defined(AUTHENTICATION) || defined(ENCRYPTION)
+       auth_encrypt_init(hostname, host, "TELNETD", 1);
+#endif
+
+       init_env();
+       /*
+        * get terminal type.
+        */
+       *user_name = 0;
+       level = getterminaltype(user_name);
+       setenv("TERM", terminaltype ? terminaltype : "network", 1);
+
+       /*
+        * Start up the login process on the slave side of the terminal
+        */
+#ifndef        convex
+       startslave(host, level, user_name);
+
+#if    defined(_SC_CRAY_SECURE_SYS)
+       if (secflag) {
+               if (setulvl(dv.dv_actlvl) < 0)
+                       fatal(net,"cannot setulvl()");
+               if (setucmp(dv.dv_actcmp) < 0)
+                       fatal(net, "cannot setucmp()");
+       }
+#endif /* _SC_CRAY_SECURE_SYS */
+
+       telnet(net, pty);  /* begin server processing */
+#else
+       telnet(net, pty, host);
+#endif
+       /*NOTREACHED*/
+}  /* end of doit */
+
+#if    defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50)
+       int
+Xterm_output(ibufp, obuf, icountp, ocount)
+       char **ibufp, *obuf;
+       int *icountp, ocount;
+{
+       int ret;
+       ret = term_output(*ibufp, obuf, *icountp, ocount);
+       *ibufp += *icountp;
+       *icountp = 0;
+       return(ret);
+}
+#define        term_output     Xterm_output
+#endif /* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */
+
+/*
+ * Main loop.  Select from pty and network, and
+ * hand data to telnet receiver finite state machine.
+ */
+       void
+#ifndef        convex
+telnet(f, p)
+#else
+telnet(f, p, host)
+#endif
+       int f, p;
+#ifdef convex
+       char *host;
+#endif
+{
+       int on = 1;
+#define        TABBUFSIZ       512
+       char    defent[TABBUFSIZ];
+       char    defstrs[TABBUFSIZ];
+#undef TABBUFSIZ
+       char *HE;
+       char *HN;
+       char *IM;
+       void netflush();
+       int nfd;
+
+       /*
+        * Initialize the slc mapping table.
+        */
+       get_slc_defaults();
+
+       /*
+        * Do some tests where it is desireable to wait for a response.
+        * Rather than doing them slowly, one at a time, do them all
+        * at once.
+        */
+       if (my_state_is_wont(TELOPT_SGA))
+               send_will(TELOPT_SGA, 1);
+       /*
+        * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
+        * because 4.2 clients are unable to deal with TCP urgent data.
+        *
+        * To find out, we send out a "DO ECHO".  If the remote system
+        * answers "WILL ECHO" it is probably a 4.2 client, and we note
+        * that fact ("WILL ECHO" ==> that the client will echo what
+        * WE, the server, sends it; it does NOT mean that the client will
+        * echo the terminal input).
+        */
+       send_do(TELOPT_ECHO, 1);
+
+#ifdef LINEMODE
+       if (his_state_is_wont(TELOPT_LINEMODE)) {
+               /* Query the peer for linemode support by trying to negotiate
+                * the linemode option.
+                */
+               linemode = 0;
+               editmode = 0;
+               send_do(TELOPT_LINEMODE, 1);  /* send do linemode */
+       }
+#endif /* LINEMODE */
+
+       /*
+        * Send along a couple of other options that we wish to negotiate.
+        */
+       send_do(TELOPT_NAWS, 1);
+       send_will(TELOPT_STATUS, 1);
+       flowmode = 1;           /* default flow control state */
+       restartany = -1;        /* uninitialized... */
+       send_do(TELOPT_LFLOW, 1);
+
+       /*
+        * Spin, waiting for a response from the DO ECHO.  However,
+        * some REALLY DUMB telnets out there might not respond
+        * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
+        * telnets so far seem to respond with WONT for a DO that
+        * they don't understand...) because by the time we get the
+        * response, it will already have processed the DO ECHO.
+        * Kludge upon kludge.
+        */
+       while (his_will_wont_is_changing(TELOPT_NAWS))
+               ttloop();
+
+       /*
+        * But...
+        * The client might have sent a WILL NAWS as part of its
+        * startup code; if so, we'll be here before we get the
+        * response to the DO ECHO.  We'll make the assumption
+        * that any implementation that understands about NAWS
+        * is a modern enough implementation that it will respond
+        * to our DO ECHO request; hence we'll do another spin
+        * waiting for the ECHO option to settle down, which is
+        * what we wanted to do in the first place...
+        */
+       if (his_want_state_is_will(TELOPT_ECHO) &&
+           his_state_is_will(TELOPT_NAWS)) {
+               while (his_will_wont_is_changing(TELOPT_ECHO))
+                       ttloop();
+       }
+       /*
+        * On the off chance that the telnet client is broken and does not
+        * respond to the DO ECHO we sent, (after all, we did send the
+        * DO NAWS negotiation after the DO ECHO, and we won't get here
+        * until a response to the DO NAWS comes back) simulate the
+        * receipt of a will echo.  This will also send a WONT ECHO
+        * to the client, since we assume that the client failed to
+        * respond because it believes that it is already in DO ECHO
+        * mode, which we do not want.
+        */
+       if (his_want_state_is_will(TELOPT_ECHO)) {
+               DIAG(TD_OPTIONS,
+                       {sprintf(nfrontp, "td: simulating recv\r\n");
+                        nfrontp += strlen(nfrontp);});
+               willoption(TELOPT_ECHO);
+       }
+
+       /*
+        * Finally, to clean things up, we turn on our echo.  This
+        * will break stupid 4.2 telnets out of local terminal echo.
+        */
+
+       if (my_state_is_wont(TELOPT_ECHO))
+               send_will(TELOPT_ECHO, 1);
+
+#ifndef        STREAMSPTY
+       /*
+        * Turn on packet mode
+        */
+       (void) ioctl(p, TIOCPKT, (char *)&on);
+#endif
+
+#if    defined(LINEMODE) && defined(KLUDGELINEMODE)
+       /*
+        * Continuing line mode support.  If client does not support
+        * real linemode, attempt to negotiate kludge linemode by sending
+        * the do timing mark sequence.
+        */
+       if (lmodetype < REAL_LINEMODE)
+               send_do(TELOPT_TM, 1);
+#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
+
+       /*
+        * Call telrcv() once to pick up anything received during
+        * terminal type negotiation, 4.2/4.3 determination, and
+        * linemode negotiation.
+        */
+       telrcv();
+
+       (void) ioctl(f, FIONBIO, (char *)&on);
+       (void) ioctl(p, FIONBIO, (char *)&on);
+#if    defined(CRAY2) && defined(UNICOS5)
+       init_termdriver(f, p, interrupt, sendbrk);
+#endif
+
+#if    defined(SO_OOBINLINE)
+       (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
+                               (char *)&on, sizeof on);
+#endif /* defined(SO_OOBINLINE) */
+
+#ifdef SIGTSTP
+       (void) signal(SIGTSTP, SIG_IGN);
+#endif
+#ifdef SIGTTOU
+       /*
+        * Ignoring SIGTTOU keeps the kernel from blocking us
+        * in ttioct() in /sys/tty.c.
+        */
+       (void) signal(SIGTTOU, SIG_IGN);
+#endif
+
+       (void) signal(SIGCHLD, cleanup);
+
+#if    defined(CRAY2) && defined(UNICOS5)
+       /*
+        * Cray-2 will send a signal when pty modes are changed by slave
+        * side.  Set up signal handler now.
+        */
+       if ((int)signal(SIGUSR1, termstat) < 0)
+               perror("signal");
+       else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0)
+               perror("ioctl:TCSIGME");
+       /*
+        * Make processing loop check terminal characteristics early on.
+        */
+       termstat();
+#endif
+
+#ifdef  TIOCNOTTY
+       {
+               register int t;
+               t = open(_PATH_TTY, O_RDWR);
+               if (t >= 0) {
+                       (void) ioctl(t, TIOCNOTTY, (char *)0);
+                       (void) close(t);
+               }
+       }
+#endif
+
+#if    defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY)
+       (void) setsid();
+       ioctl(p, TIOCSCTTY, 0);
+#endif
+
+       /*
+        * Show banner that getty never gave.
+        *
+        * We put the banner in the pty input buffer.  This way, it
+        * gets carriage return null processing, etc., just like all
+        * other pty --> client data.
+        */
+
+#if    !defined(CRAY) || !defined(NEWINIT)
+       if (getenv("USER"))
+               hostinfo = 0;
+#endif
+
+       if (getent(defent, "default") == 1) {
+               char *Getstr();
+               char *cp=defstrs;
+
+               HE = Getstr("he", &cp);
+               HN = Getstr("hn", &cp);
+               IM = Getstr("im", &cp);
+               if (HN && *HN) {
+                       (void) strncpy(host_name, HN, sizeof(host_name)-1);
+                       hostname[sizeof(host_name)-1] = '\0';
+               }
+               if (IM == 0)
+                       IM = "";
+       } else {
+               IM = DEFAULT_IM;
+               HE = 0;
+       }
+       edithost(HE, host_name);
+       if (hostinfo && *IM)
+               putf(IM, ptyibuf2);
+
+       if (pcc)
+               (void) strncat(ptyibuf2, ptyip, pcc+1);
+       ptyip = ptyibuf2;
+       pcc = strlen(ptyip);
+#ifdef LINEMODE
+       /*
+        * Last check to make sure all our states are correct.
+        */
+       init_termbuf();
+       localstat();
+#endif /* LINEMODE */
+
+       DIAG(TD_REPORT,
+               {sprintf(nfrontp, "td: Entering processing loop\r\n");
+                nfrontp += strlen(nfrontp);});
+
+#ifdef convex
+       startslave(host);
+#endif
+
+       nfd = ((f > p) ? f : p) + 1;
+       for (;;) {
+               fd_set ibits, obits, xbits;
+               register int c;
+
+               if (ncc < 0 && pcc < 0)
+                       break;
+
+#if    defined(CRAY2) && defined(UNICOS5)
+               if (needtermstat)
+                       _termstat();
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+               FD_ZERO(&ibits);
+               FD_ZERO(&obits);
+               FD_ZERO(&xbits);
+               /*
+                * Never look for input if there's still
+                * stuff in the corresponding output buffer
+                */
+               if (nfrontp - nbackp || pcc > 0) {
+                       FD_SET(f, &obits);
+               } else {
+                       FD_SET(p, &ibits);
+               }
+               if (pfrontp - pbackp || ncc > 0) {
+                       FD_SET(p, &obits);
+               } else {
+                       FD_SET(f, &ibits);
+               }
+               if (!SYNCHing) {
+                       FD_SET(f, &xbits);
+               }
+               if ((c = select(nfd, &ibits, &obits, &xbits,
+                                               (struct timeval *)0)) < 1) {
+                       if (c == -1) {
+                               if (errno == EINTR) {
+                                       continue;
+                               }
+                       }
+                       sleep(5);
+                       continue;
+               }
+
+               /*
+                * Any urgent data?
+                */
+               if (FD_ISSET(net, &xbits)) {
+                   SYNCHing = 1;
+               }
+
+               /*
+                * Something to read from the network...
+                */
+               if (FD_ISSET(net, &ibits)) {
+#if    !defined(SO_OOBINLINE)
+                       /*
+                        * In 4.2 (and 4.3 beta) systems, the
+                        * OOB indication and data handling in the kernel
+                        * is such that if two separate TCP Urgent requests
+                        * come in, one byte of TCP data will be overlaid.
+                        * This is fatal for Telnet, but we try to live
+                        * with it.
+                        *
+                        * In addition, in 4.2 (and...), a special protocol
+                        * is needed to pick up the TCP Urgent data in
+                        * the correct sequence.
+                        *
+                        * What we do is:  if we think we are in urgent
+                        * mode, we look to see if we are "at the mark".
+                        * If we are, we do an OOB receive.  If we run
+                        * this twice, we will do the OOB receive twice,
+                        * but the second will fail, since the second
+                        * time we were "at the mark", but there wasn't
+                        * any data there (the kernel doesn't reset
+                        * "at the mark" until we do a normal read).
+                        * Once we've read the OOB data, we go ahead
+                        * and do normal reads.
+                        *
+                        * There is also another problem, which is that
+                        * since the OOB byte we read doesn't put us
+                        * out of OOB state, and since that byte is most
+                        * likely the TELNET DM (data mark), we would
+                        * stay in the TELNET SYNCH (SYNCHing) state.
+                        * So, clocks to the rescue.  If we've "just"
+                        * received a DM, then we test for the
+                        * presence of OOB data when the receive OOB
+                        * fails (and AFTER we did the normal mode read
+                        * to clear "at the mark").
+                        */
+                   if (SYNCHing) {
+                       int atmark;
+
+                       (void) ioctl(net, SIOCATMARK, (char *)&atmark);
+                       if (atmark) {
+                           ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
+                           if ((ncc == -1) && (errno == EINVAL)) {
+                               ncc = read(net, netibuf, sizeof (netibuf));
+                               if (sequenceIs(didnetreceive, gotDM)) {
+                                   SYNCHing = stilloob(net);
+                               }
+                           }
+                       } else {
+                           ncc = read(net, netibuf, sizeof (netibuf));
+                       }
+                   } else {
+                       ncc = read(net, netibuf, sizeof (netibuf));
+                   }
+                   settimer(didnetreceive);
+#else  /* !defined(SO_OOBINLINE)) */
+                   ncc = read(net, netibuf, sizeof (netibuf));
+#endif /* !defined(SO_OOBINLINE)) */
+                   if (ncc < 0 && errno == EWOULDBLOCK)
+                       ncc = 0;
+                   else {
+                       if (ncc <= 0) {
+                           break;
+                       }
+                       netip = netibuf;
+                   }
+                   DIAG((TD_REPORT | TD_NETDATA),
+                           {sprintf(nfrontp, "td: netread %d chars\r\n", ncc);
+                            nfrontp += strlen(nfrontp);});
+                   DIAG(TD_NETDATA, printdata("nd", netip, ncc));
+               }
+
+               /*
+                * Something to read from the pty...
+                */
+               if (FD_ISSET(p, &ibits)) {
+#ifndef        STREAMSPTY
+                       pcc = read(p, ptyibuf, BUFSIZ);
+#else
+                       pcc = readstream(p, ptyibuf, BUFSIZ);
+#endif
+                       /*
+                        * On some systems, if we try to read something
+                        * off the master side before the slave side is
+                        * opened, we get EIO.
+                        */
+                       if (pcc < 0 && (errno == EWOULDBLOCK ||
+#ifdef EAGAIN
+                                       errno == EAGAIN ||
+#endif
+                                       errno == EIO)) {
+                               pcc = 0;
+                       } else {
+                               if (pcc <= 0)
+                                       break;
+#if    !defined(CRAY2) || !defined(UNICOS5)
+#ifdef LINEMODE
+                               /*
+                                * If ioctl from pty, pass it through net
+                                */
+                               if (ptyibuf[0] & TIOCPKT_IOCTL) {
+                                       copy_termbuf(ptyibuf+1, pcc-1);
+                                       localstat();
+                                       pcc = 1;
+                               }
+#endif /* LINEMODE */
+                               if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
+                                       netclear();     /* clear buffer back */
+#ifndef        NO_URGENT
+                                       /*
+                                        * There are client telnets on some
+                                        * operating systems get screwed up
+                                        * royally if we send them urgent
+                                        * mode data.
+                                        */
+                                       *nfrontp++ = IAC;
+                                       *nfrontp++ = DM;
+                                       neturg = nfrontp-1; /* off by one XXX */
+                                       DIAG(TD_OPTIONS,
+                                           printoption("td: send IAC", DM));
+
+#endif
+                               }
+                               if (his_state_is_will(TELOPT_LFLOW) &&
+                                   (ptyibuf[0] &
+                                    (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
+                                       int newflow =
+                                           ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
+                                       if (newflow != flowmode) {
+                                               flowmode = newflow;
+                                               (void) sprintf(nfrontp,
+                                                       "%c%c%c%c%c%c",
+                                                       IAC, SB, TELOPT_LFLOW,
+                                                       flowmode ? LFLOW_ON
+                                                                : LFLOW_OFF,
+                                                       IAC, SE);
+                                               nfrontp += 6;
+                                               DIAG(TD_OPTIONS, printsub('>',
+                                                   (unsigned char *)nfrontp-4,
+                                                   4););
+                                       }
+                               }
+                               pcc--;
+                               ptyip = ptyibuf+1;
+#else  /* defined(CRAY2) && defined(UNICOS5) */
+                               if (!uselinemode) {
+                                       unpcc = pcc;
+                                       unptyip = ptyibuf;
+                                       pcc = term_output(&unptyip, ptyibuf2,
+                                                               &unpcc, BUFSIZ);
+                                       ptyip = ptyibuf2;
+                               } else
+                                       ptyip = ptyibuf;
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+                       }
+               }
+
+               while (pcc > 0) {
+                       if ((&netobuf[BUFSIZ] - nfrontp) < 2)
+                               break;
+                       c = *ptyip++ & 0377, pcc--;
+                       if (c == IAC)
+                               *nfrontp++ = c;
+#if    defined(CRAY2) && defined(UNICOS5)
+                       else if (c == '\n' &&
+                                    my_state_is_wont(TELOPT_BINARY) && newmap)
+                               *nfrontp++ = '\r';
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+                       *nfrontp++ = c;
+                       if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
+                               if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
+                                       *nfrontp++ = *ptyip++ & 0377;
+                                       pcc--;
+                               } else
+                                       *nfrontp++ = '\0';
+                       }
+               }
+#if    defined(CRAY2) && defined(UNICOS5)
+               /*
+                * If chars were left over from the terminal driver,
+                * note their existence.
+                */
+               if (!uselinemode && unpcc) {
+                       pcc = unpcc;
+                       unpcc = 0;
+                       ptyip = unptyip;
+               }
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+
+               if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
+                       netflush();
+               if (ncc > 0)
+                       telrcv();
+               if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
+                       ptyflush();
+       }
+       cleanup(0);
+}  /* end of telnet */
+
+#ifndef        TCSIG
+# ifdef        TIOCSIG
+#  define TCSIG TIOCSIG
+# endif
+#endif
+
+#ifdef STREAMSPTY
+
+int flowison = -1;  /* current state of flow: -1 is unknown */
+
+int readstream(p, ibuf, bufsize)
+       int p;
+       char *ibuf;
+       int bufsize;
+{
+       int flags = 0;
+       int ret = 0;
+       struct termios *tsp;
+       struct termio *tp;
+       struct iocblk *ip;
+       char vstop, vstart;
+       int ixon;
+       int newflow;
+
+       strbufc.maxlen = BUFSIZ;
+       strbufc.buf = (char *)ctlbuf;
+       strbufd.maxlen = bufsize-1;
+       strbufd.len = 0;
+       strbufd.buf = ibuf+1;
+       ibuf[0] = 0;
+
+       ret = getmsg(p, &strbufc, &strbufd, &flags);
+       if (ret < 0)  /* error of some sort -- probably EAGAIN */
+               return(-1);
+
+       if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
+               /* data message */
+               if (strbufd.len > 0) {                  /* real data */
+                       return(strbufd.len + 1);        /* count header char */
+               } else {
+                       /* nothing there */
+                       errno = EAGAIN;
+                       return(-1);
+               }
+       }
+
+       /*
+        * It's a control message.  Return 1, to look at the flag we set
+        */
+
+       switch (ctlbuf[0]) {
+       case M_FLUSH:
+               if (ibuf[1] & FLUSHW)
+                       ibuf[0] = TIOCPKT_FLUSHWRITE;
+               return(1);
+
+       case M_IOCTL:
+               ip = (struct iocblk *) (ibuf+1);
+
+               switch (ip->ioc_cmd) {
+               case TCSETS:
+               case TCSETSW:
+               case TCSETSF:
+                       tsp = (struct termios *)
+                                       (ibuf+1 + sizeof(struct iocblk));
+                       vstop = tsp->c_cc[VSTOP];
+                       vstart = tsp->c_cc[VSTART];
+                       ixon = tsp->c_iflag & IXON;
+                       break;
+               case TCSETA:
+               case TCSETAW:
+               case TCSETAF:
+                       tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));
+                       vstop = tp->c_cc[VSTOP];
+                       vstart = tp->c_cc[VSTART];
+                       ixon = tp->c_iflag & IXON;
+                       break;
+               default:
+                       errno = EAGAIN;
+                       return(-1);
+               }
+
+               newflow =  (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
+               if (newflow != flowison) {  /* it's a change */
+                       flowison = newflow;
+                       ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
+                       return(1);
+               }
+       }
+
+       /* nothing worth doing anything about */
+       errno = EAGAIN;
+       return(-1);
+}
+#endif /* STREAMSPTY */
+
+/*
+ * Send interrupt to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write intr char.
+ */
+       void
+interrupt()
+{
+       ptyflush();     /* half-hearted */
+
+#if defined(STREAMSPTY) && defined(TIOCSIGNAL)
+       /* Streams PTY style ioctl to post a signal */
+       {
+               int sig = SIGINT;
+               (void) ioctl(pty, TIOCSIGNAL, &sig);
+               (void) ioctl(pty, I_FLUSH, FLUSHR);
+       }
+#else
+#ifdef TCSIG
+       (void) ioctl(pty, TCSIG, (char *)SIGINT);
+#else  /* TCSIG */
+       init_termbuf();
+       *pfrontp++ = slctab[SLC_IP].sptr ?
+                       (unsigned char)*slctab[SLC_IP].sptr : '\177';
+#endif /* TCSIG */
+#endif
+}
+
+/*
+ * Send quit to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write quit char.
+ */
+       void
+sendbrk()
+{
+       ptyflush();     /* half-hearted */
+#ifdef TCSIG
+       (void) ioctl(pty, TCSIG, (char *)SIGQUIT);
+#else  /* TCSIG */
+       init_termbuf();
+       *pfrontp++ = slctab[SLC_ABORT].sptr ?
+                       (unsigned char)*slctab[SLC_ABORT].sptr : '\034';
+#endif /* TCSIG */
+}
+
+       void
+sendsusp()
+{
+#ifdef SIGTSTP
+       ptyflush();     /* half-hearted */
+# ifdef        TCSIG
+       (void) ioctl(pty, TCSIG, (char *)SIGTSTP);
+# else /* TCSIG */
+       *pfrontp++ = slctab[SLC_SUSP].sptr ?
+                       (unsigned char)*slctab[SLC_SUSP].sptr : '\032';
+# endif        /* TCSIG */
+#endif /* SIGTSTP */
+}
+
+/*
+ * When we get an AYT, if ^T is enabled, use that.  Otherwise,
+ * just send back "[Yes]".
+ */
+       void
+recv_ayt()
+{
+#if    defined(SIGINFO) && defined(TCSIG)
+       if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
+               (void) ioctl(pty, TCSIG, (char *)SIGINFO);
+               return;
+       }
+#endif
+       (void) strcpy(nfrontp, "\r\n[Yes]\r\n");
+       nfrontp += 9;
+}
+
+       void
+doeof()
+{
+       init_termbuf();
+
+#if    defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN)
+       if (!tty_isediting()) {
+               extern char oldeofc;
+               *pfrontp++ = oldeofc;
+               return;
+       }
+#endif
+       *pfrontp++ = slctab[SLC_EOF].sptr ?
+                       (unsigned char)*slctab[SLC_EOF].sptr : '\004';
+}
diff --git a/telnetd.tproj/telnetd.h b/telnetd.tproj/telnetd.h
new file mode 100644 (file)
index 0000000..56ccdcd
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)telnetd.h   8.1 (Berkeley) 6/4/93
+ */
+
+
+#include "defs.h"
+#include "ext.h"
+#include <syslog.h>
+
+#ifdef DIAGNOSTICS
+#define        DIAG(a,b)       if (diagnostic & (a)) b
+#else
+#define        DIAG(a,b)
+#endif
+
+/* other external variables */
+extern char **environ;
+extern int errno;
+
diff --git a/telnetd.tproj/termstat.c b/telnetd.tproj/termstat.c
new file mode 100644 (file)
index 0000000..0705dec
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#include "telnetd.h"
+
+/*
+ * local variables
+ */
+int def_tspeed = -1, def_rspeed = -1;
+#ifdef TIOCSWINSZ
+int def_row = 0, def_col = 0;
+#endif
+#ifdef LINEMODE
+static int _terminit = 0;
+#endif /* LINEMODE */
+
+#if    defined(CRAY2) && defined(UNICOS5)
+int    newmap = 1;     /* nonzero if \n maps to ^M^J */
+#endif
+
+#ifdef LINEMODE
+/*
+ * localstat
+ *
+ * This function handles all management of linemode.
+ *
+ * Linemode allows the client to do the local editing of data
+ * and send only complete lines to the server.  Linemode state is
+ * based on the state of the pty driver.  If the pty is set for
+ * external processing, then we can use linemode.  Further, if we
+ * can use real linemode, then we can look at the edit control bits
+ * in the pty to determine what editing the client should do.
+ *
+ * Linemode support uses the following state flags to keep track of
+ * current and desired linemode state.
+ *     alwayslinemode : true if -l was specified on the telnetd
+ *     command line.  It means to have linemode on as much as
+ *     possible.
+ *
+ *     lmodetype: signifies whether the client can
+ *     handle real linemode, or if use of kludgeomatic linemode
+ *     is preferred.  It will be set to one of the following:
+ *             REAL_LINEMODE : use linemode option
+ *             NO_KLUDGE : don't initiate kludge linemode.
+ *             KLUDGE_LINEMODE : use kludge linemode
+ *             NO_LINEMODE : client is ignorant of linemode
+ *
+ *     linemode, uselinemode : linemode is true if linemode
+ *     is currently on, uselinemode is the state that we wish
+ *     to be in.  If another function wishes to turn linemode
+ *     on or off, it sets or clears uselinemode.
+ *
+ *     editmode, useeditmode : like linemode/uselinemode, but
+ *     these contain the edit mode states (edit and trapsig).
+ *
+ * The state variables correspond to some of the state information
+ * in the pty.
+ *     linemode:
+ *             In real linemode, this corresponds to whether the pty
+ *             expects external processing of incoming data.
+ *             In kludge linemode, this more closely corresponds to the
+ *             whether normal processing is on or not.  (ICANON in
+ *             system V, or COOKED mode in BSD.)
+ *             If the -l option was specified (alwayslinemode), then
+ *             an attempt is made to force external processing on at
+ *             all times.
+ *
+ * The following heuristics are applied to determine linemode
+ * handling within the server.
+ *     1) Early on in starting up the server, an attempt is made
+ *        to negotiate the linemode option.  If this succeeds
+ *        then lmodetype is set to REAL_LINEMODE and all linemode
+ *        processing occurs in the context of the linemode option.
+ *     2) If the attempt to negotiate the linemode option failed,
+ *        and the "-k" (don't initiate kludge linemode) isn't set,
+ *        then we try to use kludge linemode.  We test for this
+ *        capability by sending "do Timing Mark".  If a positive
+ *        response comes back, then we assume that the client
+ *        understands kludge linemode (ech!) and the
+ *        lmodetype flag is set to KLUDGE_LINEMODE.
+ *     3) Otherwise, linemode is not supported at all and
+ *        lmodetype remains set to NO_LINEMODE (which happens
+ *        to be 0 for convenience).
+ *     4) At any time a command arrives that implies a higher
+ *        state of linemode support in the client, we move to that
+ *        linemode support.
+ *
+ * A short explanation of kludge linemode is in order here.
+ *     1) The heuristic to determine support for kludge linemode
+ *        is to send a do timing mark.  We assume that a client
+ *        that supports timing marks also supports kludge linemode.
+ *        A risky proposition at best.
+ *     2) Further negotiation of linemode is done by changing the
+ *        the server's state regarding SGA.  If server will SGA,
+ *        then linemode is off, if server won't SGA, then linemode
+ *        is on.
+ */
+       void
+localstat()
+{
+       void netflush();
+       int need_will_echo = 0;
+
+#if    defined(CRAY2) && defined(UNICOS5)
+       /*
+        * Keep track of that ol' CR/NL mapping while we're in the
+        * neighborhood.
+        */
+       newmap = tty_isnewmap();
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+
+       /*
+        * Check for state of BINARY options.
+        */
+       if (tty_isbinaryin()) {
+               if (his_want_state_is_wont(TELOPT_BINARY))
+                       send_do(TELOPT_BINARY, 1);
+       } else {
+               if (his_want_state_is_will(TELOPT_BINARY))
+                       send_dont(TELOPT_BINARY, 1);
+       }
+
+       if (tty_isbinaryout()) {
+               if (my_want_state_is_wont(TELOPT_BINARY))
+                       send_will(TELOPT_BINARY, 1);
+       } else {
+               if (my_want_state_is_will(TELOPT_BINARY))
+                       send_wont(TELOPT_BINARY, 1);
+       }
+
+       /*
+        * Check for changes to flow control if client supports it.
+        */
+       flowstat();
+
+       /*
+        * Check linemode on/off state
+        */
+       uselinemode = tty_linemode();
+
+       /*
+        * If alwayslinemode is on, and pty is changing to turn it off, then
+        * force linemode back on.
+        */
+       if (alwayslinemode && linemode && !uselinemode) {
+               uselinemode = 1;
+               tty_setlinemode(uselinemode);
+       }
+
+#ifdef ENCRYPTION
+       /*
+        * If the terminal is not echoing, but editing is enabled,
+        * something like password input is going to happen, so
+        * if we the other side is not currently sending encrypted
+        * data, ask the other side to start encrypting.
+        */
+       if (his_state_is_will(TELOPT_ENCRYPT)) {
+               static int enc_passwd = 0;
+               if (uselinemode && !tty_isecho() && tty_isediting()
+                   && (enc_passwd == 0) && !decrypt_input) {
+                       encrypt_send_request_start();
+                       enc_passwd = 1;
+               } else if (enc_passwd) {
+                       encrypt_send_request_end();
+                       enc_passwd = 0;
+               }
+       }
+#endif /* ENCRYPTION */
+
+       /*
+        * Do echo mode handling as soon as we know what the
+        * linemode is going to be.
+        * If the pty has echo turned off, then tell the client that
+        * the server will echo.  If echo is on, then the server
+        * will echo if in character mode, but in linemode the
+        * client should do local echoing.  The state machine will
+        * not send anything if it is unnecessary, so don't worry
+        * about that here.
+        *
+        * If we need to send the WILL ECHO (because echo is off),
+        * then delay that until after we have changed the MODE.
+        * This way, when the user is turning off both editing
+        * and echo, the client will get editing turned off first.
+        * This keeps the client from going into encryption mode
+        * and then right back out if it is doing auto-encryption
+        * when passwords are being typed.
+        */
+       if (uselinemode) {
+               if (tty_isecho())
+                       send_wont(TELOPT_ECHO, 1);
+               else
+                       need_will_echo = 1;
+#ifdef KLUDGELINEMODE
+               if (lmodetype == KLUDGE_OK)
+                       lmodetype = KLUDGE_LINEMODE;
+#endif
+       }
+
+       /*
+        * If linemode is being turned off, send appropriate
+        * command and then we're all done.
+        */
+        if (!uselinemode && linemode) {
+# ifdef        KLUDGELINEMODE
+               if (lmodetype == REAL_LINEMODE) {
+# endif        /* KLUDGELINEMODE */
+                       send_dont(TELOPT_LINEMODE, 1);
+# ifdef        KLUDGELINEMODE
+               } else if (lmodetype == KLUDGE_LINEMODE)
+                       send_will(TELOPT_SGA, 1);
+# endif        /* KLUDGELINEMODE */
+               send_will(TELOPT_ECHO, 1);
+               linemode = uselinemode;
+               goto done;
+       }
+
+# ifdef        KLUDGELINEMODE
+       /*
+        * If using real linemode check edit modes for possible later use.
+        * If we are in kludge linemode, do the SGA negotiation.
+        */
+       if (lmodetype == REAL_LINEMODE) {
+# endif        /* KLUDGELINEMODE */
+               useeditmode = 0;
+               if (tty_isediting())
+                       useeditmode |= MODE_EDIT;
+               if (tty_istrapsig())
+                       useeditmode |= MODE_TRAPSIG;
+               if (tty_issofttab())
+                       useeditmode |= MODE_SOFT_TAB;
+               if (tty_islitecho())
+                       useeditmode |= MODE_LIT_ECHO;
+# ifdef        KLUDGELINEMODE
+       } else if (lmodetype == KLUDGE_LINEMODE) {
+               if (tty_isediting() && uselinemode)
+                       send_wont(TELOPT_SGA, 1);
+               else
+                       send_will(TELOPT_SGA, 1);
+       }
+# endif        /* KLUDGELINEMODE */
+
+       /*
+        * Negotiate linemode on if pty state has changed to turn it on.
+        * Send appropriate command and send along edit mode, then all done.
+        */
+       if (uselinemode && !linemode) {
+# ifdef        KLUDGELINEMODE
+               if (lmodetype == KLUDGE_LINEMODE) {
+                       send_wont(TELOPT_SGA, 1);
+               } else if (lmodetype == REAL_LINEMODE) {
+# endif        /* KLUDGELINEMODE */
+                       send_do(TELOPT_LINEMODE, 1);
+                       /* send along edit modes */
+                       (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
+                               TELOPT_LINEMODE, LM_MODE, useeditmode,
+                               IAC, SE);
+                       nfrontp += 7;
+                       editmode = useeditmode;
+# ifdef        KLUDGELINEMODE
+               }
+# endif        /* KLUDGELINEMODE */
+               linemode = uselinemode;
+               goto done;
+       }
+
+# ifdef        KLUDGELINEMODE
+       /*
+        * None of what follows is of any value if not using
+        * real linemode.
+        */
+       if (lmodetype < REAL_LINEMODE)
+               goto done;
+# endif        /* KLUDGELINEMODE */
+
+       if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
+               /*
+                * If edit mode changed, send edit mode.
+                */
+                if (useeditmode != editmode) {
+                       /*
+                        * Send along appropriate edit mode mask.
+                        */
+                       (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
+                               TELOPT_LINEMODE, LM_MODE, useeditmode,
+                               IAC, SE);
+                       nfrontp += 7;
+                       editmode = useeditmode;
+               }
+
+
+               /*
+                * Check for changes to special characters in use.
+                */
+               start_slc(0);
+               check_slc();
+               (void) end_slc(0);
+       }
+
+done:
+       if (need_will_echo)
+               send_will(TELOPT_ECHO, 1);
+       /*
+        * Some things should be deferred until after the pty state has
+        * been set by the local process.  Do those things that have been
+        * deferred now.  This only happens once.
+        */
+       if (_terminit == 0) {
+               _terminit = 1;
+               defer_terminit();
+       }
+
+       netflush();
+       set_termbuf();
+       return;
+
+}  /* end of localstat */
+#endif /* LINEMODE */
+
+/*
+ * flowstat
+ *
+ * Check for changes to flow control
+ */
+       void
+flowstat()
+{
+       if (his_state_is_will(TELOPT_LFLOW)) {
+               if (tty_flowmode() != flowmode) {
+                       flowmode = tty_flowmode();
+                       (void) sprintf(nfrontp, "%c%c%c%c%c%c",
+                                       IAC, SB, TELOPT_LFLOW,
+                                       flowmode ? LFLOW_ON : LFLOW_OFF,
+                                       IAC, SE);
+                       nfrontp += 6;
+               }
+               if (tty_restartany() != restartany) {
+                       restartany = tty_restartany();
+                       (void) sprintf(nfrontp, "%c%c%c%c%c%c",
+                                       IAC, SB, TELOPT_LFLOW,
+                                       restartany ? LFLOW_RESTART_ANY
+                                                  : LFLOW_RESTART_XON,
+                                       IAC, SE);
+                       nfrontp += 6;
+               }
+       }
+}
+
+/*
+ * clientstat
+ *
+ * Process linemode related requests from the client.
+ * Client can request a change to only one of linemode, editmode or slc's
+ * at a time, and if using kludge linemode, then only linemode may be
+ * affected.
+ */
+       void
+clientstat(code, parm1, parm2)
+       register int code, parm1, parm2;
+{
+       void netflush();
+
+       /*
+        * Get a copy of terminal characteristics.
+        */
+       init_termbuf();
+
+       /*
+        * Process request from client. code tells what it is.
+        */
+       switch (code) {
+#ifdef LINEMODE
+       case TELOPT_LINEMODE:
+               /*
+                * Don't do anything unless client is asking us to change
+                * modes.
+                */
+               uselinemode = (parm1 == WILL);
+               if (uselinemode != linemode) {
+# ifdef        KLUDGELINEMODE
+                       /*
+                        * If using kludge linemode, make sure that
+                        * we can do what the client asks.
+                        * We can not turn off linemode if alwayslinemode
+                        * and the ICANON bit is set.
+                        */
+                       if (lmodetype == KLUDGE_LINEMODE) {
+                               if (alwayslinemode && tty_isediting()) {
+                                       uselinemode = 1;
+                               }
+                       }
+
+                       /*
+                        * Quit now if we can't do it.
+                        */
+                       if (uselinemode == linemode)
+                               return;
+
+                       /*
+                        * If using real linemode and linemode is being
+                        * turned on, send along the edit mode mask.
+                        */
+                       if (lmodetype == REAL_LINEMODE && uselinemode)
+# else /* KLUDGELINEMODE */
+                       if (uselinemode)
+# endif        /* KLUDGELINEMODE */
+                       {
+                               useeditmode = 0;
+                               if (tty_isediting())
+                                       useeditmode |= MODE_EDIT;
+                               if (tty_istrapsig)
+                                       useeditmode |= MODE_TRAPSIG;
+                               if (tty_issofttab())
+                                       useeditmode |= MODE_SOFT_TAB;
+                               if (tty_islitecho())
+                                       useeditmode |= MODE_LIT_ECHO;
+                               (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
+                                       SB, TELOPT_LINEMODE, LM_MODE,
+                                                       useeditmode, IAC, SE);
+                               nfrontp += 7;
+                               editmode = useeditmode;
+                       }
+
+
+                       tty_setlinemode(uselinemode);
+
+                       linemode = uselinemode;
+
+                       if (!linemode)
+                               send_will(TELOPT_ECHO, 1);
+               }
+               break;
+
+       case LM_MODE:
+           {
+               register int ack, changed;
+
+               /*
+                * Client has sent along a mode mask.  If it agrees with
+                * what we are currently doing, ignore it; if not, it could
+                * be viewed as a request to change.  Note that the server
+                * will change to the modes in an ack if it is different from
+                * what we currently have, but we will not ack the ack.
+                */
+                useeditmode &= MODE_MASK;
+                ack = (useeditmode & MODE_ACK);
+                useeditmode &= ~MODE_ACK;
+
+                if (changed = (useeditmode ^ editmode)) {
+                       /*
+                        * This check is for a timing problem.  If the
+                        * state of the tty has changed (due to the user
+                        * application) we need to process that info
+                        * before we write in the state contained in the
+                        * ack!!!  This gets out the new MODE request,
+                        * and when the ack to that command comes back
+                        * we'll set it and be in the right mode.
+                        */
+                       if (ack)
+                               localstat();
+                       if (changed & MODE_EDIT)
+                               tty_setedit(useeditmode & MODE_EDIT);
+
+                       if (changed & MODE_TRAPSIG)
+                               tty_setsig(useeditmode & MODE_TRAPSIG);
+
+                       if (changed & MODE_SOFT_TAB)
+                               tty_setsofttab(useeditmode & MODE_SOFT_TAB);
+
+                       if (changed & MODE_LIT_ECHO)
+                               tty_setlitecho(useeditmode & MODE_LIT_ECHO);
+
+                       set_termbuf();
+
+                       if (!ack) {
+                               (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
+                                       SB, TELOPT_LINEMODE, LM_MODE,
+                                       useeditmode|MODE_ACK,
+                                       IAC, SE);
+                               nfrontp += 7;
+                       }
+
+                       editmode = useeditmode;
+               }
+
+               break;
+
+           }  /* end of case LM_MODE */
+#endif /* LINEMODE */
+
+       case TELOPT_NAWS:
+#ifdef TIOCSWINSZ
+           {
+               struct winsize ws;
+
+               def_col = parm1;
+               def_row = parm2;
+#ifdef LINEMODE
+               /*
+                * Defer changing window size until after terminal is
+                * initialized.
+                */
+               if (terminit() == 0)
+                       return;
+#endif /* LINEMODE */
+
+               /*
+                * Change window size as requested by client.
+                */
+
+               ws.ws_col = parm1;
+               ws.ws_row = parm2;
+               (void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
+           }
+#endif /* TIOCSWINSZ */
+
+               break;
+
+       case TELOPT_TSPEED:
+           {
+               def_tspeed = parm1;
+               def_rspeed = parm2;
+#ifdef LINEMODE
+               /*
+                * Defer changing the terminal speed.
+                */
+               if (terminit() == 0)
+                       return;
+#endif /* LINEMODE */
+               /*
+                * Change terminal speed as requested by client.
+                * We set the receive speed first, so that if we can't
+                * store seperate receive and transmit speeds, the transmit
+                * speed will take precedence.
+                */
+               tty_rspeed(parm2);
+               tty_tspeed(parm1);
+               set_termbuf();
+
+               break;
+
+           }  /* end of case TELOPT_TSPEED */
+
+       default:
+               /* What? */
+               break;
+       }  /* end of switch */
+
+#if    defined(CRAY2) && defined(UNICOS5)
+       /*
+        * Just in case of the likely event that we changed the pty state.
+        */
+       rcv_ioctl();
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+
+       netflush();
+
+}  /* end of clientstat */
+
+#if    defined(CRAY2) && defined(UNICOS5)
+       void
+termstat()
+{
+       needtermstat = 1;
+}
+
+       void
+_termstat()
+{
+       needtermstat = 0;
+       init_termbuf();
+       localstat();
+       rcv_ioctl();
+}
+#endif /* defined(CRAY2) && defined(UNICOS5) */
+
+#ifdef LINEMODE
+/*
+ * defer_terminit
+ *
+ * Some things should not be done until after the login process has started
+ * and all the pty modes are set to what they are supposed to be.  This
+ * function is called when the pty state has been processed for the first time.
+ * It calls other functions that do things that were deferred in each module.
+ */
+       void
+defer_terminit()
+{
+
+       /*
+        * local stuff that got deferred.
+        */
+       if (def_tspeed != -1) {
+               clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed);
+               def_tspeed = def_rspeed = 0;
+       }
+
+#ifdef TIOCSWINSZ
+       if (def_col || def_row) {
+               struct winsize ws;
+
+               memset((char *)&ws, 0, sizeof(ws));
+               ws.ws_col = def_col;
+               ws.ws_row = def_row;
+               (void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
+       }
+#endif
+
+       /*
+        * The only other module that currently defers anything.
+        */
+       deferslc();
+
+}  /* end of defer_terminit */
+
+/*
+ * terminit
+ *
+ * Returns true if the pty state has been processed yet.
+ */
+       int
+terminit()
+{
+       return(_terminit);
+
+}  /* end of terminit */
+#endif /* LINEMODE */
diff --git a/telnetd.tproj/utility.c b/telnetd.tproj/utility.c
new file mode 100644 (file)
index 0000000..9154811
--- /dev/null
@@ -0,0 +1,1215 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)utility.c  8.4 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#define PRINTOPTIONS
+#include "telnetd.h"
+
+/*
+ * utility functions performing io related tasks
+ */
+
+/*
+ * ttloop
+ *
+ *     A small subroutine to flush the network output buffer, get some data
+ * from the network, and pass it through the telnet state machine.  We
+ * also flush the pty input buffer (by dropping its data) if it becomes
+ * too full.
+ */
+
+    void
+ttloop()
+{
+    void netflush();
+
+    DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n");
+                    nfrontp += strlen(nfrontp);});
+    if (nfrontp-nbackp) {
+       netflush();
+    }
+    ncc = read(net, netibuf, sizeof netibuf);
+    if (ncc < 0) {
+       syslog(LOG_INFO, "ttloop:  read: %m\n");
+       exit(1);
+    } else if (ncc == 0) {
+       syslog(LOG_INFO, "ttloop:  peer died: %m\n");
+       exit(1);
+    }
+    DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc);
+                    nfrontp += strlen(nfrontp);});
+    netip = netibuf;
+    telrcv();                  /* state machine */
+    if (ncc > 0) {
+       pfrontp = pbackp = ptyobuf;
+       telrcv();
+    }
+}  /* end of ttloop */
+
+/*
+ * Check a descriptor to see if out of band data exists on it.
+ */
+    int
+stilloob(s)
+    int        s;              /* socket number */
+{
+    static struct timeval timeout = { 0 };
+    fd_set     excepts;
+    int value;
+
+    do {
+       FD_ZERO(&excepts);
+       FD_SET(s, &excepts);
+       value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
+    } while ((value == -1) && (errno == EINTR));
+
+    if (value < 0) {
+       fatalperror(pty, "select");
+    }
+    if (FD_ISSET(s, &excepts)) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+       void
+ptyflush()
+{
+       int n;
+
+       if ((n = pfrontp - pbackp) > 0) {
+               DIAG((TD_REPORT | TD_PTYDATA),
+                       { sprintf(nfrontp, "td: ptyflush %d chars\r\n", n);
+                         nfrontp += strlen(nfrontp); });
+               DIAG(TD_PTYDATA, printdata("pd", pbackp, n));
+               n = write(pty, pbackp, n);
+       }
+       if (n < 0) {
+               if (errno == EWOULDBLOCK || errno == EINTR)
+                       return;
+               cleanup(0);
+       }
+       pbackp += n;
+       if (pbackp == pfrontp)
+               pbackp = pfrontp = ptyobuf;
+}
+
+/*
+ * nextitem()
+ *
+ *     Return the address of the next "item" in the TELNET data
+ * stream.  This will be the address of the next character if
+ * the current address is a user data character, or it will
+ * be the address of the character following the TELNET command
+ * if the current address is a TELNET IAC ("I Am a Command")
+ * character.
+ */
+    char *
+nextitem(current)
+    char       *current;
+{
+    if ((*current&0xff) != IAC) {
+       return current+1;
+    }
+    switch (*(current+1)&0xff) {
+    case DO:
+    case DONT:
+    case WILL:
+    case WONT:
+       return current+3;
+    case SB:           /* loop forever looking for the SE */
+       {
+           register char *look = current+2;
+
+           for (;;) {
+               if ((*look++&0xff) == IAC) {
+                   if ((*look++&0xff) == SE) {
+                       return look;
+                   }
+               }
+           }
+       }
+    default:
+       return current+2;
+    }
+}  /* end of nextitem */
+
+
+/*
+ * netclear()
+ *
+ *     We are about to do a TELNET SYNCH operation.  Clear
+ * the path to the network.
+ *
+ *     Things are a bit tricky since we may have sent the first
+ * byte or so of a previous TELNET command into the network.
+ * So, we have to scan the network buffer from the beginning
+ * until we are up to where we want to be.
+ *
+ *     A side effect of what we do, just to keep things
+ * simple, is to clear the urgent data pointer.  The principal
+ * caller should be setting the urgent data pointer AFTER calling
+ * us in any case.
+ */
+    void
+netclear()
+{
+    register char *thisitem, *next;
+    char *good;
+#define        wewant(p)       ((nfrontp > p) && ((*p&0xff) == IAC) && \
+                               ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+
+#ifdef ENCRYPTION
+    thisitem = nclearto > netobuf ? nclearto : netobuf;
+#else  /* ENCRYPTION */
+    thisitem = netobuf;
+#endif /* ENCRYPTION */
+
+    while ((next = nextitem(thisitem)) <= nbackp) {
+       thisitem = next;
+    }
+
+    /* Now, thisitem is first before/at boundary. */
+
+#ifdef ENCRYPTION
+    good = nclearto > netobuf ? nclearto : netobuf;
+#else  /* ENCRYPTION */
+    good = netobuf;    /* where the good bytes go */
+#endif /* ENCRYPTION */
+
+    while (nfrontp > thisitem) {
+       if (wewant(thisitem)) {
+           int length;
+
+           next = thisitem;
+           do {
+               next = nextitem(next);
+           } while (wewant(next) && (nfrontp > next));
+           length = next-thisitem;
+           memmove(good, thisitem, length);
+           good += length;
+           thisitem = next;
+       } else {
+           thisitem = nextitem(thisitem);
+       }
+    }
+
+    nbackp = netobuf;
+    nfrontp = good;            /* next byte to be sent */
+    neturg = 0;
+}  /* end of netclear */
+
+/*
+ *  netflush
+ *             Send as much data as possible to the network,
+ *     handling requests for urgent data.
+ */
+    void
+netflush()
+{
+    int n;
+    extern int not42;
+
+    if ((n = nfrontp - nbackp) > 0) {
+       DIAG(TD_REPORT,
+           { sprintf(nfrontp, "td: netflush %d chars\r\n", n);
+             n += strlen(nfrontp);  /* get count first */
+             nfrontp += strlen(nfrontp);  /* then move pointer */
+           });
+#ifdef ENCRYPTION
+       if (encrypt_output) {
+               char *s = nclearto ? nclearto : nbackp;
+               if (nfrontp - s > 0) {
+                       (*encrypt_output)((unsigned char *)s, nfrontp-s);
+                       nclearto = nfrontp;
+               }
+       }
+#endif /* ENCRYPTION */
+       /*
+        * if no urgent data, or if the other side appears to be an
+        * old 4.2 client (and thus unable to survive TCP urgent data),
+        * write the entire buffer in non-OOB mode.
+        */
+       if ((neturg == 0) || (not42 == 0)) {
+           n = write(net, nbackp, n);  /* normal write */
+       } else {
+           n = neturg - nbackp;
+           /*
+            * In 4.2 (and 4.3) systems, there is some question about
+            * what byte in a sendOOB operation is the "OOB" data.
+            * To make ourselves compatible, we only send ONE byte
+            * out of band, the one WE THINK should be OOB (though
+            * we really have more the TCP philosophy of urgent data
+            * rather than the Unix philosophy of OOB data).
+            */
+           if (n > 1) {
+               n = send(net, nbackp, n-1, 0);  /* send URGENT all by itself */
+           } else {
+               n = send(net, nbackp, n, MSG_OOB);      /* URGENT data */
+           }
+       }
+    }
+    if (n < 0) {
+       if (errno == EWOULDBLOCK || errno == EINTR)
+               return;
+       cleanup(0);
+    }
+    nbackp += n;
+#ifdef ENCRYPTION
+    if (nbackp > nclearto)
+       nclearto = 0;
+#endif /* ENCRYPTION */
+    if (nbackp >= neturg) {
+       neturg = 0;
+    }
+    if (nbackp == nfrontp) {
+       nbackp = nfrontp = netobuf;
+#ifdef ENCRYPTION
+       nclearto = 0;
+#endif /* ENCRYPTION */
+    }
+    return;
+}  /* end of netflush */
+
+
+/*
+ * writenet
+ *
+ * Just a handy little function to write a bit of raw data to the net.
+ * It will force a transmit of the buffer if necessary
+ *
+ * arguments
+ *    ptr - A pointer to a character string to write
+ *    len - How many bytes to write
+ */
+       void
+writenet(ptr, len)
+       register unsigned char *ptr;
+       register int len;
+{
+       /* flush buffer if no room for new data) */
+       if ((&netobuf[BUFSIZ] - nfrontp) < len) {
+               /* if this fails, don't worry, buffer is a little big */
+               netflush();
+       }
+
+       memmove(nfrontp, ptr, len);
+       nfrontp += len;
+
+}  /* end of writenet */
+
+
+/*
+ * miscellaneous functions doing a variety of little jobs follow ...
+ */
+
+
+       void
+fatal(f, msg)
+       int f;
+       char *msg;
+{
+       char buf[BUFSIZ];
+
+       (void) sprintf(buf, "telnetd: %s.\r\n", msg);
+#ifdef ENCRYPTION
+       if (encrypt_output) {
+               /*
+                * Better turn off encryption first....
+                * Hope it flushes...
+                */
+               encrypt_send_end();
+               netflush();
+       }
+#endif /* ENCRYPTION */
+       (void) write(f, buf, (int)strlen(buf));
+       sleep(1);       /*XXX*/
+       exit(1);
+}
+
+       void
+fatalperror(f, msg)
+       int f;
+       char *msg;
+{
+       char buf[BUFSIZ], *strerror();
+
+       (void) sprintf(buf, "%s: %s", msg, strerror(errno));
+       fatal(f, buf);
+}
+
+char editedhost[32];
+
+       void
+edithost(pat, host)
+       register char *pat;
+       register char *host;
+{
+       register char *res = editedhost;
+       char *strncpy();
+
+       if (!pat)
+               pat = "";
+       while (*pat) {
+               switch (*pat) {
+
+               case '#':
+                       if (*host)
+                               host++;
+                       break;
+
+               case '@':
+                       if (*host)
+                               *res++ = *host++;
+                       break;
+
+               default:
+                       *res++ = *pat;
+                       break;
+               }
+               if (res == &editedhost[sizeof editedhost - 1]) {
+                       *res = '\0';
+                       return;
+               }
+               pat++;
+       }
+       if (*host)
+               (void) strncpy(res, host,
+                               sizeof editedhost - (res - editedhost) -1);
+       else
+               *res = '\0';
+       editedhost[sizeof editedhost - 1] = '\0';
+}
+
+static char *putlocation;
+
+       void
+putstr(s)
+       register char *s;
+{
+
+       while (*s)
+               putchr(*s++);
+}
+
+       void
+putchr(cc)
+       int cc;
+{
+       *putlocation++ = cc;
+}
+
+/*
+ * This is split on two lines so that SCCS will not see the M
+ * between two % signs and expand it...
+ */
+static char fmtstr[] = { "%l:%M\
+%P on %A, %d %B %Y" };
+
+       void
+putf(cp, where)
+       register char *cp;
+       char *where;
+{
+       char *slash;
+       time_t t;
+       char db[100];
+#ifdef STREAMSPTY
+       extern char *strchr();
+#else
+       extern char *strrchr();
+#endif
+
+       putlocation = where;
+
+       while (*cp) {
+               if (*cp != '%') {
+                       putchr(*cp++);
+                       continue;
+               }
+               switch (*++cp) {
+
+               case 't':
+#ifdef STREAMSPTY
+                       /* names are like /dev/pts/2 -- we want pts/2 */
+                       slash = strchr(line+1, '/');
+#else
+                       slash = strrchr(line, '/');
+#endif
+                       if (slash == (char *) 0)
+                               putstr(line);
+                       else
+                               putstr(&slash[1]);
+                       break;
+
+               case 'h':
+                       putstr(editedhost);
+                       break;
+
+               case 'd':
+                       (void)time(&t);
+                       (void)strftime(db, sizeof(db), fmtstr, localtime(&t));
+                       putstr(db);
+                       break;
+
+               case '%':
+                       putchr('%');
+                       break;
+               }
+               cp++;
+       }
+}
+
+#ifdef DIAGNOSTICS
+/*
+ * Print telnet options and commands in plain text, if possible.
+ */
+       void
+printoption(fmt, option)
+       register char *fmt;
+       register int option;
+{
+       if (TELOPT_OK(option))
+               sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option));
+       else if (TELCMD_OK(option))
+               sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option));
+       else
+               sprintf(nfrontp, "%s %d\r\n", fmt, option);
+       nfrontp += strlen(nfrontp);
+       return;
+}
+
+    void
+printsub(direction, pointer, length)
+    char               direction;      /* '<' or '>' */
+    unsigned char      *pointer;       /* where suboption data sits */
+    int                        length;         /* length of suboption data */
+{
+    register int i;
+    char buf[512];
+
+       if (!(diagnostic & TD_OPTIONS))
+               return;
+
+       if (direction) {
+           sprintf(nfrontp, "td: %s suboption ",
+                                       direction == '<' ? "recv" : "send");
+           nfrontp += strlen(nfrontp);
+           if (length >= 3) {
+               register int j;
+
+               i = pointer[length-2];
+               j = pointer[length-1];
+
+               if (i != IAC || j != SE) {
+                   sprintf(nfrontp, "(terminated by ");
+                   nfrontp += strlen(nfrontp);
+                   if (TELOPT_OK(i))
+                       sprintf(nfrontp, "%s ", TELOPT(i));
+                   else if (TELCMD_OK(i))
+                       sprintf(nfrontp, "%s ", TELCMD(i));
+                   else
+                       sprintf(nfrontp, "%d ", i);
+                   nfrontp += strlen(nfrontp);
+                   if (TELOPT_OK(j))
+                       sprintf(nfrontp, "%s", TELOPT(j));
+                   else if (TELCMD_OK(j))
+                       sprintf(nfrontp, "%s", TELCMD(j));
+                   else
+                       sprintf(nfrontp, "%d", j);
+                   nfrontp += strlen(nfrontp);
+                   sprintf(nfrontp, ", not IAC SE!) ");
+                   nfrontp += strlen(nfrontp);
+               }
+           }
+           length -= 2;
+       }
+       if (length < 1) {
+           sprintf(nfrontp, "(Empty suboption??\?)");
+           nfrontp += strlen(nfrontp);
+           return;
+       }
+       switch (pointer[0]) {
+       case TELOPT_TTYPE:
+           sprintf(nfrontp, "TERMINAL-TYPE ");
+           nfrontp += strlen(nfrontp);
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2);
+               break;
+           case TELQUAL_SEND:
+               sprintf(nfrontp, "SEND");
+               break;
+           default:
+               sprintf(nfrontp,
+                               "- unknown qualifier %d (0x%x).",
+                               pointer[1], pointer[1]);
+           }
+           nfrontp += strlen(nfrontp);
+           break;
+       case TELOPT_TSPEED:
+           sprintf(nfrontp, "TERMINAL-SPEED");
+           nfrontp += strlen(nfrontp);
+           if (length < 2) {
+               sprintf(nfrontp, " (empty suboption??\?)");
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2);
+               nfrontp += strlen(nfrontp);
+               break;
+           default:
+               if (pointer[1] == 1)
+                   sprintf(nfrontp, " SEND");
+               else
+                   sprintf(nfrontp, " %d (unknown)", pointer[1]);
+               nfrontp += strlen(nfrontp);
+               for (i = 2; i < length; i++) {
+                   sprintf(nfrontp, " ?%d?", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+               }
+               break;
+           }
+           break;
+
+       case TELOPT_LFLOW:
+           sprintf(nfrontp, "TOGGLE-FLOW-CONTROL");
+           nfrontp += strlen(nfrontp);
+           if (length < 2) {
+               sprintf(nfrontp, " (empty suboption??\?)");
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           switch (pointer[1]) {
+           case LFLOW_OFF:
+               sprintf(nfrontp, " OFF"); break;
+           case LFLOW_ON:
+               sprintf(nfrontp, " ON"); break;
+           case LFLOW_RESTART_ANY:
+               sprintf(nfrontp, " RESTART-ANY"); break;
+           case LFLOW_RESTART_XON:
+               sprintf(nfrontp, " RESTART-XON"); break;
+           default:
+               sprintf(nfrontp, " %d (unknown)", pointer[1]);
+           }
+           nfrontp += strlen(nfrontp);
+           for (i = 2; i < length; i++) {
+               sprintf(nfrontp, " ?%d?", pointer[i]);
+               nfrontp += strlen(nfrontp);
+           }
+           break;
+
+       case TELOPT_NAWS:
+           sprintf(nfrontp, "NAWS");
+           nfrontp += strlen(nfrontp);
+           if (length < 2) {
+               sprintf(nfrontp, " (empty suboption??\?)");
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           if (length == 2) {
+               sprintf(nfrontp, " ?%d?", pointer[1]);
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           sprintf(nfrontp, " %d %d (%d)",
+               pointer[1], pointer[2],
+               (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
+           nfrontp += strlen(nfrontp);
+           if (length == 4) {
+               sprintf(nfrontp, " ?%d?", pointer[3]);
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           sprintf(nfrontp, " %d %d (%d)",
+               pointer[3], pointer[4],
+               (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
+           nfrontp += strlen(nfrontp);
+           for (i = 5; i < length; i++) {
+               sprintf(nfrontp, " ?%d?", pointer[i]);
+               nfrontp += strlen(nfrontp);
+           }
+           break;
+
+       case TELOPT_LINEMODE:
+           sprintf(nfrontp, "LINEMODE ");
+           nfrontp += strlen(nfrontp);
+           if (length < 2) {
+               sprintf(nfrontp, " (empty suboption??\?)");
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           switch (pointer[1]) {
+           case WILL:
+               sprintf(nfrontp, "WILL ");
+               goto common;
+           case WONT:
+               sprintf(nfrontp, "WONT ");
+               goto common;
+           case DO:
+               sprintf(nfrontp, "DO ");
+               goto common;
+           case DONT:
+               sprintf(nfrontp, "DONT ");
+           common:
+               nfrontp += strlen(nfrontp);
+               if (length < 3) {
+                   sprintf(nfrontp, "(no option??\?)");
+                   nfrontp += strlen(nfrontp);
+                   break;
+               }
+               switch (pointer[2]) {
+               case LM_FORWARDMASK:
+                   sprintf(nfrontp, "Forward Mask");
+                   nfrontp += strlen(nfrontp);
+                   for (i = 3; i < length; i++) {
+                       sprintf(nfrontp, " %x", pointer[i]);
+                       nfrontp += strlen(nfrontp);
+                   }
+                   break;
+               default:
+                   sprintf(nfrontp, "%d (unknown)", pointer[2]);
+                   nfrontp += strlen(nfrontp);
+                   for (i = 3; i < length; i++) {
+                       sprintf(nfrontp, " %d", pointer[i]);
+                       nfrontp += strlen(nfrontp);
+                   }
+                   break;
+               }
+               break;
+
+           case LM_SLC:
+               sprintf(nfrontp, "SLC");
+               nfrontp += strlen(nfrontp);
+               for (i = 2; i < length - 2; i += 3) {
+                   if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
+                       sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
+                   else
+                       sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]);
+                   nfrontp += strlen(nfrontp);
+                   switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
+                   case SLC_NOSUPPORT:
+                       sprintf(nfrontp, " NOSUPPORT"); break;
+                   case SLC_CANTCHANGE:
+                       sprintf(nfrontp, " CANTCHANGE"); break;
+                   case SLC_VARIABLE:
+                       sprintf(nfrontp, " VARIABLE"); break;
+                   case SLC_DEFAULT:
+                       sprintf(nfrontp, " DEFAULT"); break;
+                   }
+                   nfrontp += strlen(nfrontp);
+                   sprintf(nfrontp, "%s%s%s",
+                       pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
+                       pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
+                       pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
+                   nfrontp += strlen(nfrontp);
+                   if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
+                                               SLC_FLUSHOUT| SLC_LEVELBITS)) {
+                       sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]);
+                       nfrontp += strlen(nfrontp);
+                   }
+                   sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]);
+                   nfrontp += strlen(nfrontp);
+                   if ((pointer[i+SLC_VALUE] == IAC) &&
+                       (pointer[i+SLC_VALUE+1] == IAC))
+                               i++;
+               }
+               for (; i < length; i++) {
+                   sprintf(nfrontp, " ?%d?", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+               }
+               break;
+
+           case LM_MODE:
+               sprintf(nfrontp, "MODE ");
+               nfrontp += strlen(nfrontp);
+               if (length < 3) {
+                   sprintf(nfrontp, "(no mode??\?)");
+                   nfrontp += strlen(nfrontp);
+                   break;
+               }
+               {
+                   char tbuf[32];
+                   sprintf(tbuf, "%s%s%s%s%s",
+                       pointer[2]&MODE_EDIT ? "|EDIT" : "",
+                       pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
+                       pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
+                       pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
+                       pointer[2]&MODE_ACK ? "|ACK" : "");
+                   sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0");
+                   nfrontp += strlen(nfrontp);
+               }
+               if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) {
+                   sprintf(nfrontp, " (0x%x)", pointer[2]);
+                   nfrontp += strlen(nfrontp);
+               }
+               for (i = 3; i < length; i++) {
+                   sprintf(nfrontp, " ?0x%x?", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+               }
+               break;
+           default:
+               sprintf(nfrontp, "%d (unknown)", pointer[1]);
+               nfrontp += strlen(nfrontp);
+               for (i = 2; i < length; i++) {
+                   sprintf(nfrontp, " %d", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+               }
+           }
+           break;
+
+       case TELOPT_STATUS: {
+           register char *cp;
+           register int j, k;
+
+           sprintf(nfrontp, "STATUS");
+           nfrontp += strlen(nfrontp);
+
+           switch (pointer[1]) {
+           default:
+               if (pointer[1] == TELQUAL_SEND)
+                   sprintf(nfrontp, " SEND");
+               else
+                   sprintf(nfrontp, " %d (unknown)", pointer[1]);
+               nfrontp += strlen(nfrontp);
+               for (i = 2; i < length; i++) {
+                   sprintf(nfrontp, " ?%d?", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+               }
+               break;
+           case TELQUAL_IS:
+               sprintf(nfrontp, " IS\r\n");
+               nfrontp += strlen(nfrontp);
+
+               for (i = 2; i < length; i++) {
+                   switch(pointer[i]) {
+                   case DO:    cp = "DO"; goto common2;
+                   case DONT:  cp = "DONT"; goto common2;
+                   case WILL:  cp = "WILL"; goto common2;
+                   case WONT:  cp = "WONT"; goto common2;
+                   common2:
+                       i++;
+                       if (TELOPT_OK(pointer[i]))
+                           sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i]));
+                       else
+                           sprintf(nfrontp, " %s %d", cp, pointer[i]);
+                       nfrontp += strlen(nfrontp);
+
+                       sprintf(nfrontp, "\r\n");
+                       nfrontp += strlen(nfrontp);
+                       break;
+
+                   case SB:
+                       sprintf(nfrontp, " SB ");
+                       nfrontp += strlen(nfrontp);
+                       i++;
+                       j = k = i;
+                       while (j < length) {
+                           if (pointer[j] == SE) {
+                               if (j+1 == length)
+                                   break;
+                               if (pointer[j+1] == SE)
+                                   j++;
+                               else
+                                   break;
+                           }
+                           pointer[k++] = pointer[j++];
+                       }
+                       printsub(0, &pointer[i], k - i);
+                       if (i < length) {
+                           sprintf(nfrontp, " SE");
+                           nfrontp += strlen(nfrontp);
+                           i = j;
+                       } else
+                           i = j - 1;
+
+                       sprintf(nfrontp, "\r\n");
+                       nfrontp += strlen(nfrontp);
+
+                       break;
+
+                   default:
+                       sprintf(nfrontp, " %d", pointer[i]);
+                       nfrontp += strlen(nfrontp);
+                       break;
+                   }
+               }
+               break;
+           }
+           break;
+         }
+
+       case TELOPT_XDISPLOC:
+           sprintf(nfrontp, "X-DISPLAY-LOCATION ");
+           nfrontp += strlen(nfrontp);
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2);
+               break;
+           case TELQUAL_SEND:
+               sprintf(nfrontp, "SEND");
+               break;
+           default:
+               sprintf(nfrontp, "- unknown qualifier %d (0x%x).",
+                               pointer[1], pointer[1]);
+           }
+           nfrontp += strlen(nfrontp);
+           break;
+
+       case TELOPT_NEW_ENVIRON:
+           sprintf(nfrontp, "NEW-ENVIRON ");
+           goto env_common1;
+       case TELOPT_OLD_ENVIRON:
+           sprintf(nfrontp, "OLD-ENVIRON");
+       env_common1:
+           nfrontp += strlen(nfrontp);
+           switch (pointer[1]) {
+           case TELQUAL_IS:
+               sprintf(nfrontp, "IS ");
+               goto env_common;
+           case TELQUAL_SEND:
+               sprintf(nfrontp, "SEND ");
+               goto env_common;
+           case TELQUAL_INFO:
+               sprintf(nfrontp, "INFO ");
+           env_common:
+               nfrontp += strlen(nfrontp);
+               {
+                   register int noquote = 2;
+                   for (i = 2; i < length; i++ ) {
+                       switch (pointer[i]) {
+                       case NEW_ENV_VAR:
+                           sprintf(nfrontp, "\" VAR " + noquote);
+                           nfrontp += strlen(nfrontp);
+                           noquote = 2;
+                           break;
+
+                       case NEW_ENV_VALUE:
+                           sprintf(nfrontp, "\" VALUE " + noquote);
+                           nfrontp += strlen(nfrontp);
+                           noquote = 2;
+                           break;
+
+                       case ENV_ESC:
+                           sprintf(nfrontp, "\" ESC " + noquote);
+                           nfrontp += strlen(nfrontp);
+                           noquote = 2;
+                           break;
+
+                       case ENV_USERVAR:
+                           sprintf(nfrontp, "\" USERVAR " + noquote);
+                           nfrontp += strlen(nfrontp);
+                           noquote = 2;
+                           break;
+
+                       default:
+                       def_case:
+                           if (isprint(pointer[i]) && pointer[i] != '"') {
+                               if (noquote) {
+                                   *nfrontp++ = '"';
+                                   noquote = 0;
+                               }
+                               *nfrontp++ = pointer[i];
+                           } else {
+                               sprintf(nfrontp, "\" %03o " + noquote,
+                                                       pointer[i]);
+                               nfrontp += strlen(nfrontp);
+                               noquote = 2;
+                           }
+                           break;
+                       }
+                   }
+                   if (!noquote)
+                       *nfrontp++ = '"';
+                   break;
+               }
+           }
+           break;
+
+#if    defined(AUTHENTICATION)
+       case TELOPT_AUTHENTICATION:
+           sprintf(nfrontp, "AUTHENTICATION");
+           nfrontp += strlen(nfrontp);
+
+           if (length < 2) {
+               sprintf(nfrontp, " (empty suboption??\?)");
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           switch (pointer[1]) {
+           case TELQUAL_REPLY:
+           case TELQUAL_IS:
+               sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ?
+                                                       "IS" : "REPLY");
+               nfrontp += strlen(nfrontp);
+               if (AUTHTYPE_NAME_OK(pointer[2]))
+                   sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2]));
+               else
+                   sprintf(nfrontp, "%d ", pointer[2]);
+               nfrontp += strlen(nfrontp);
+               if (length < 3) {
+                   sprintf(nfrontp, "(partial suboption??\?)");
+                   nfrontp += strlen(nfrontp);
+                   break;
+               }
+               sprintf(nfrontp, "%s|%s",
+                       ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+                       "CLIENT" : "SERVER",
+                       ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+                       "MUTUAL" : "ONE-WAY");
+               nfrontp += strlen(nfrontp);
+
+               auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+               sprintf(nfrontp, "%s", buf);
+               nfrontp += strlen(nfrontp);
+               break;
+
+           case TELQUAL_SEND:
+               i = 2;
+               sprintf(nfrontp, " SEND ");
+               nfrontp += strlen(nfrontp);
+               while (i < length) {
+                   if (AUTHTYPE_NAME_OK(pointer[i]))
+                       sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i]));
+                   else
+                       sprintf(nfrontp, "%d ", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+                   if (++i >= length) {
+                       sprintf(nfrontp, "(partial suboption??\?)");
+                       nfrontp += strlen(nfrontp);
+                       break;
+                   }
+                   sprintf(nfrontp, "%s|%s ",
+                       ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+                                                       "CLIENT" : "SERVER",
+                       ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+                                                       "MUTUAL" : "ONE-WAY");
+                   nfrontp += strlen(nfrontp);
+                   ++i;
+               }
+               break;
+
+           case TELQUAL_NAME:
+               i = 2;
+               sprintf(nfrontp, " NAME \"");
+               nfrontp += strlen(nfrontp);
+               while (i < length)
+                   *nfrontp += pointer[i++];
+               *nfrontp += '"';
+               break;
+
+           default:
+                   for (i = 2; i < length; i++) {
+                       sprintf(nfrontp, " ?%d?", pointer[i]);
+                       nfrontp += strlen(nfrontp);
+                   }
+                   break;
+           }
+           break;
+#endif
+
+#ifdef ENCRYPTION
+       case TELOPT_ENCRYPT:
+           sprintf(nfrontp, "ENCRYPT");
+           nfrontp += strlen(nfrontp);
+           if (length < 2) {
+               sprintf(nfrontp, " (empty suboption??\?)");
+               nfrontp += strlen(nfrontp);
+               break;
+           }
+           switch (pointer[1]) {
+           case ENCRYPT_START:
+               sprintf(nfrontp, " START");
+               nfrontp += strlen(nfrontp);
+               break;
+
+           case ENCRYPT_END:
+               sprintf(nfrontp, " END");
+               nfrontp += strlen(nfrontp);
+               break;
+
+           case ENCRYPT_REQSTART:
+               sprintf(nfrontp, " REQUEST-START");
+               nfrontp += strlen(nfrontp);
+               break;
+
+           case ENCRYPT_REQEND:
+               sprintf(nfrontp, " REQUEST-END");
+               nfrontp += strlen(nfrontp);
+               break;
+
+           case ENCRYPT_IS:
+           case ENCRYPT_REPLY:
+               sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ?
+                                                       "IS" : "REPLY");
+               nfrontp += strlen(nfrontp);
+               if (length < 3) {
+                   sprintf(nfrontp, " (partial suboption??\?)");
+                   nfrontp += strlen(nfrontp);
+                   break;
+               }
+               if (ENCTYPE_NAME_OK(pointer[2]))
+                   sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2]));
+               else
+                   sprintf(nfrontp, " %d (unknown)", pointer[2]);
+               nfrontp += strlen(nfrontp);
+
+               encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+               sprintf(nfrontp, "%s", buf);
+               nfrontp += strlen(nfrontp);
+               break;
+
+           case ENCRYPT_SUPPORT:
+               i = 2;
+               sprintf(nfrontp, " SUPPORT ");
+               nfrontp += strlen(nfrontp);
+               while (i < length) {
+                   if (ENCTYPE_NAME_OK(pointer[i]))
+                       sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i]));
+                   else
+                       sprintf(nfrontp, "%d ", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+                   i++;
+               }
+               break;
+
+           case ENCRYPT_ENC_KEYID:
+               sprintf(nfrontp, " ENC_KEYID", pointer[1]);
+               nfrontp += strlen(nfrontp);
+               goto encommon;
+
+           case ENCRYPT_DEC_KEYID:
+               sprintf(nfrontp, " DEC_KEYID", pointer[1]);
+               nfrontp += strlen(nfrontp);
+               goto encommon;
+
+           default:
+               sprintf(nfrontp, " %d (unknown)", pointer[1]);
+               nfrontp += strlen(nfrontp);
+           encommon:
+               for (i = 2; i < length; i++) {
+                   sprintf(nfrontp, " %d", pointer[i]);
+                   nfrontp += strlen(nfrontp);
+               }
+               break;
+           }
+           break;
+#endif /* ENCRYPTION */
+
+       default:
+           if (TELOPT_OK(pointer[0]))
+               sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0]));
+           else
+               sprintf(nfrontp, "%d (unknown)", pointer[i]);
+           nfrontp += strlen(nfrontp);
+           for (i = 1; i < length; i++) {
+               sprintf(nfrontp, " %d", pointer[i]);
+               nfrontp += strlen(nfrontp);
+           }
+           break;
+       }
+       sprintf(nfrontp, "\r\n");
+       nfrontp += strlen(nfrontp);
+}
+
+/*
+ * Dump a data buffer in hex and ascii to the output data stream.
+ */
+       void
+printdata(tag, ptr, cnt)
+       register char *tag;
+       register char *ptr;
+       register int cnt;
+{
+       register int i;
+       char xbuf[30];
+
+       while (cnt) {
+               /* flush net output buffer if no room for new data) */
+               if ((&netobuf[BUFSIZ] - nfrontp) < 80) {
+                       netflush();
+               }
+
+               /* add a line of output */
+               sprintf(nfrontp, "%s: ", tag);
+               nfrontp += strlen(nfrontp);
+               for (i = 0; i < 20 && cnt; i++) {
+                       sprintf(nfrontp, "%02x", *ptr);
+                       nfrontp += strlen(nfrontp);
+                       if (isprint(*ptr)) {
+                               xbuf[i] = *ptr;
+                       } else {
+                               xbuf[i] = '.';
+                       }
+                       if (i % 2) {
+                               *nfrontp = ' ';
+                               nfrontp++;
+                       }
+                       cnt--;
+                       ptr++;
+               }
+               xbuf[i] = '\0';
+               sprintf(nfrontp, " %s\r\n", xbuf );
+               nfrontp += strlen(nfrontp);
+       }
+}
+#endif /* DIAGNOSTICS */
diff --git a/tftp.tproj/Makefile b/tftp.tproj/Makefile
new file mode 100644 (file)
index 0000000..e28658a
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = tftp
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h tftpsubs.h
+
+CFILES = main.c tftp.c tftpsubs.c
+
+OTHERSRCS = Makefile.preamble Makefile tftp.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/tftp.tproj/Makefile.preamble b/tftp.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..925a5c7
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/tftp.tproj/PB.project b/tftp.tproj/PB.project
new file mode 100644 (file)
index 0000000..83d2fde
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (extern.h, tftpsubs.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (main.c, tftp.c, tftpsubs.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, tftp.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = tftp; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/tftp.tproj/extern.h b/tftp.tproj/extern.h
new file mode 100644 (file)
index 0000000..f41b4d4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)extern.h    8.1 (Berkeley) 6/6/93
+ */
+
+void   recvfile __P((int, char *, char *));
+void   tftp_sendfile __P((int, char *, char *));
diff --git a/tftp.tproj/main.c b/tftp.tproj/main.c
new file mode 100644 (file)
index 0000000..7e110cc
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
+
+/*
+ * TFTP User Program -- Command Interface.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#define        TIMEOUT         5               /* secs between rexmt's */
+
+struct sockaddr_in peeraddr;
+int    f;
+short   port;
+int    trace;
+int    verbose;
+int    connected;
+char   mode[32];
+char   line[BUFSIZ];
+int    margc;
+char   *margv[20];
+char   *prompt = "tftp";
+jmp_buf        toplevel;
+void   intr();
+struct servent *sp;
+
+void   get __P((int, char **));
+void   help __P((int, char **));
+void   modecmd __P((int, char **));
+void   put __P((int, char **));
+void   quit __P((int, char **));
+void   setascii __P((int, char **));
+void   setbinary __P((int, char **));
+void   setpeer __P((int, char **));
+void   setrexmt __P((int, char **));
+void   settimeout __P((int, char **));
+void   settrace __P((int, char **));
+void   setverbose __P((int, char **));
+void   status __P((int, char **));
+
+static __dead void command __P((void));
+
+static void getusage __P((char *));
+static void makeargv __P((void));
+static void putusage __P((char *));
+static void settftpmode __P((char *));
+
+#define HELPINDENT (sizeof("connect"))
+
+struct cmd {
+       char    *name;
+       char    *help;
+       void    (*handler) __P((int, char **));
+};
+
+char   vhelp[] = "toggle verbose mode";
+char   thelp[] = "toggle packet tracing";
+char   chelp[] = "connect to remote tftp";
+char   qhelp[] = "exit tftp";
+char   hhelp[] = "print help information";
+char   shelp[] = "send file";
+char   rhelp[] = "receive file";
+char   mhelp[] = "set file transfer mode";
+char   sthelp[] = "show current status";
+char   xhelp[] = "set per-packet retransmission timeout";
+char   ihelp[] = "set total retransmission timeout";
+char    ashelp[] = "set mode to netascii";
+char    bnhelp[] = "set mode to octet";
+
+struct cmd cmdtab[] = {
+       { "connect",    chelp,          setpeer },
+       { "mode",       mhelp,          modecmd },
+       { "put",        shelp,          put },
+       { "get",        rhelp,          get },
+       { "quit",       qhelp,          quit },
+       { "verbose",    vhelp,          setverbose },
+       { "trace",      thelp,          settrace },
+       { "status",     sthelp,         status },
+       { "binary",     bnhelp,         setbinary },
+       { "ascii",      ashelp,         setascii },
+       { "rexmt",      xhelp,          setrexmt },
+       { "timeout",    ihelp,          settimeout },
+       { "?",          hhelp,          help },
+       { 0 }
+};
+
+struct cmd *getcmd();
+char   *tail();
+char   *index();
+char   *rindex();
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct sockaddr_in sin;
+
+       sp = getservbyname("tftp", "udp");
+       if (sp == 0) {
+               fprintf(stderr, "tftp: udp/tftp: unknown service\n");
+               exit(1);
+       }
+       f = socket(AF_INET, SOCK_DGRAM, 0);
+       if (f < 0) {
+               perror("tftp: socket");
+               exit(3);
+       }
+       bzero((char *)&sin, sizeof(sin));
+       sin.sin_family = AF_INET;
+       if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+               perror("tftp: bind");
+               exit(1);
+       }
+       strcpy(mode, "netascii");
+       signal(SIGINT, intr);
+       if (argc > 1) {
+               if (setjmp(toplevel) != 0)
+                       exit(0);
+               setpeer(argc, argv);
+       }
+       if (setjmp(toplevel) != 0)
+               (void)putchar('\n');
+       command();
+}
+
+char    hostname[100];
+
+void
+setpeer(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct hostent *host;
+
+       if (argc < 2) {
+               strcpy(line, "Connect ");
+               printf("(to) ");
+               fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin);
+               makeargv();
+               argc = margc;
+               argv = margv;
+       }
+       if (argc > 3) {
+               printf("usage: %s host-name [port]\n", argv[0]);
+               return;
+       }
+       host = gethostbyname(argv[1]);
+       if (host) {
+               peeraddr.sin_family = host->h_addrtype;
+               bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length);
+               strcpy(hostname, host->h_name);
+       } else {
+               peeraddr.sin_family = AF_INET;
+               peeraddr.sin_addr.s_addr = inet_addr(argv[1]);
+               if (peeraddr.sin_addr.s_addr == -1) {
+                       connected = 0;
+                       printf("%s: unknown host\n", argv[1]);
+                       return;
+               }
+               strcpy(hostname, argv[1]);
+       }
+       port = sp->s_port;
+       if (argc == 3) {
+               port = atoi(argv[2]);
+               if (port < 0) {
+                       printf("%s: bad port number\n", argv[2]);
+                       connected = 0;
+                       return;
+               }
+               port = htons(port);
+       }
+       connected = 1;
+}
+
+struct modes {
+       char *m_name;
+       char *m_mode;
+} modes[] = {
+       { "ascii",      "netascii" },
+       { "netascii",   "netascii" },
+       { "binary",     "octet" },
+       { "image",      "octet" },
+       { "octet",     "octet" },
+/*      { "mail",       "mail" },       */
+       { 0,            0 }
+};
+
+void
+modecmd(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct modes *p;
+       char *sep;
+
+       if (argc < 2) {
+               printf("Using %s mode to transfer files.\n", mode);
+               return;
+       }
+       if (argc == 2) {
+               for (p = modes; p->m_name; p++)
+                       if (strcmp(argv[1], p->m_name) == 0)
+                               break;
+               if (p->m_name) {
+                       settftpmode(p->m_mode);
+                       return;
+               }
+               printf("%s: unknown mode\n", argv[1]);
+               /* drop through and print usage message */
+       }
+
+       printf("usage: %s [", argv[0]);
+       sep = " ";
+       for (p = modes; p->m_name; p++) {
+               printf("%s%s", sep, p->m_name);
+               if (*sep == ' ')
+                       sep = " | ";
+       }
+       printf(" ]\n");
+       return;
+}
+
+void
+setbinary(argc, argv)
+       int argc;
+       char *argv[];
+{      
+
+       settftpmode("octet");
+}
+
+void
+setascii(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       settftpmode("netascii");
+}
+
+static void
+settftpmode(newmode)
+       char *newmode;
+{
+       strcpy(mode, newmode);
+       if (verbose)
+               printf("mode set to %s\n", mode);
+}
+
+
+/*
+ * Send file(s).
+ */
+void
+put(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int fd;
+       register int n;
+       register char *cp, *targ;
+
+       if (argc < 2) {
+               strcpy(line, "send ");
+               printf("(file) ");
+               fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin);
+               makeargv();
+               argc = margc;
+               argv = margv;
+       }
+       if (argc < 2) {
+               putusage(argv[0]);
+               return;
+       }
+       targ = argv[argc - 1];
+       if (index(argv[argc - 1], ':')) {
+               char *cp;
+               struct hostent *hp;
+
+               for (n = 1; n < argc - 1; n++)
+                       if (index(argv[n], ':')) {
+                               putusage(argv[0]);
+                               return;
+                       }
+               cp = argv[argc - 1];
+               targ = index(cp, ':');
+               *targ++ = 0;
+               hp = gethostbyname(cp);
+               if (hp == NULL) {
+                       fprintf(stderr, "tftp: %s: ", cp);
+                       herror((char *)NULL);
+                       return;
+               }
+               bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length);
+               peeraddr.sin_family = hp->h_addrtype;
+               connected = 1;
+               strcpy(hostname, hp->h_name);
+       }
+       if (!connected) {
+               printf("No target machine specified.\n");
+               return;
+       }
+       if (argc < 4) {
+               cp = argc == 2 ? tail(targ) : argv[1];
+               fd = open(cp, O_RDONLY);
+               if (fd < 0) {
+                       fprintf(stderr, "tftp: "); perror(cp);
+                       return;
+               }
+               if (verbose)
+                       printf("putting %s to %s:%s [%s]\n",
+                               cp, hostname, targ, mode);
+               peeraddr.sin_port = port;
+               tftp_sendfile(fd, targ, mode);
+               return;
+       }
+                               /* this assumes the target is a directory */
+                               /* on a remote unix system.  hmmmm.  */
+       cp = index(targ, '\0'); 
+       *cp++ = '/';
+       for (n = 1; n < argc - 1; n++) {
+               strcpy(cp, tail(argv[n]));
+               fd = open(argv[n], O_RDONLY);
+               if (fd < 0) {
+                       fprintf(stderr, "tftp: "); perror(argv[n]);
+                       continue;
+               }
+               if (verbose)
+                       printf("putting %s to %s:%s [%s]\n",
+                               argv[n], hostname, targ, mode);
+               peeraddr.sin_port = port;
+               tftp_sendfile(fd, targ, mode);
+       }
+}
+
+static void
+putusage(s)
+       char *s;
+{
+       printf("usage: %s file ... host:target, or\n", s);
+       printf("       %s file ... target (when already connected)\n", s);
+}
+
+/*
+ * Receive file(s).
+ */
+void
+get(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int fd;
+       register int n;
+       register char *cp;
+       char *src;
+
+       if (argc < 2) {
+               strcpy(line, "get ");
+               printf("(files) ");
+               fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin);
+               makeargv();
+               argc = margc;
+               argv = margv;
+       }
+       if (argc < 2) {
+               getusage(argv[0]);
+               return;
+       }
+       if (!connected) {
+               for (n = 1; n < argc ; n++)
+                       if (index(argv[n], ':') == 0) {
+                               getusage(argv[0]);
+                               return;
+                       }
+       }
+       for (n = 1; n < argc ; n++) {
+               src = index(argv[n], ':');
+               if (src == NULL)
+                       src = argv[n];
+               else {
+                       struct hostent *hp;
+
+                       *src++ = 0;
+                       hp = gethostbyname(argv[n]);
+                       if (hp == NULL) {
+                               fprintf(stderr, "tftp: %s: ", argv[n]);
+                               herror((char *)NULL);
+                               continue;
+                       }
+                       bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
+                           hp->h_length);
+                       peeraddr.sin_family = hp->h_addrtype;
+                       connected = 1;
+                       strcpy(hostname, hp->h_name);
+               }
+               if (argc < 4) {
+                       cp = argc == 3 ? argv[2] : tail(src);
+                       fd = creat(cp, 0644);
+                       if (fd < 0) {
+                               fprintf(stderr, "tftp: "); perror(cp);
+                               return;
+                       }
+                       if (verbose)
+                               printf("getting from %s:%s to %s [%s]\n",
+                                       hostname, src, cp, mode);
+                       peeraddr.sin_port = port;
+                       recvfile(fd, src, mode);
+                       break;
+               }
+               cp = tail(src);         /* new .. jdg */
+               fd = creat(cp, 0644);
+               if (fd < 0) {
+                       fprintf(stderr, "tftp: "); perror(cp);
+                       continue;
+               }
+               if (verbose)
+                       printf("getting from %s:%s to %s [%s]\n",
+                               hostname, src, cp, mode);
+               peeraddr.sin_port = port;
+               recvfile(fd, src, mode);
+       }
+}
+
+static void
+getusage(s)
+       char *s;
+{
+       printf("usage: %s host:file host:file ... file, or\n", s);
+       printf("       %s file file ... file if connected\n", s);
+}
+
+int    rexmtval = TIMEOUT;
+
+void
+setrexmt(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int t;
+
+       if (argc < 2) {
+               strcpy(line, "Rexmt-timeout ");
+               printf("(value) ");
+               fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin);
+               makeargv();
+               argc = margc;
+               argv = margv;
+       }
+       if (argc != 2) {
+               printf("usage: %s value\n", argv[0]);
+               return;
+       }
+       t = atoi(argv[1]);
+       if (t < 0)
+               printf("%s: bad value\n", argv[1]);
+       else
+               rexmtval = t;
+}
+
+int    maxtimeout = 5 * TIMEOUT;
+
+void
+settimeout(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int t;
+
+       if (argc < 2) {
+               strcpy(line, "Maximum-timeout ");
+               printf("(value) ");
+               fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin);
+               makeargv();
+               argc = margc;
+               argv = margv;
+       }
+       if (argc != 2) {
+               printf("usage: %s value\n", argv[0]);
+               return;
+       }
+       t = atoi(argv[1]);
+       if (t < 0)
+               printf("%s: bad value\n", argv[1]);
+       else
+               maxtimeout = t;
+}
+
+void
+status(argc, argv)
+       int argc;
+       char *argv[];
+{
+       if (connected)
+               printf("Connected to %s.\n", hostname);
+       else
+               printf("Not connected.\n");
+       printf("Mode: %s Verbose: %s Tracing: %s\n", mode,
+               verbose ? "on" : "off", trace ? "on" : "off");
+       printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
+               rexmtval, maxtimeout);
+}
+
+void
+intr()
+{
+
+       signal(SIGALRM, SIG_IGN);
+       alarm(0);
+       longjmp(toplevel, -1);
+}
+
+char *
+tail(filename)
+       char *filename;
+{
+       register char *s;
+       
+       while (*filename) {
+               s = rindex(filename, '/');
+               if (s == NULL)
+                       break;
+               if (s[1])
+                       return (s + 1);
+               *s = '\0';
+       }
+       return (filename);
+}
+
+/*
+ * Command parser.
+ */
+static __dead void
+command()
+{
+       register struct cmd *c;
+
+       for (;;) {
+               printf("%s> ", prompt);
+               if (fgets(line, BUFSIZ-1, stdin) == 0) {
+                       if (feof(stdin)) {
+                               exit(0);
+                       } else {
+                               continue;
+                       }
+               }
+               if (line[0] == 0)
+                       continue;
+               makeargv();
+               if (margc == 0)
+                       continue;
+               c = getcmd(margv[0]);
+               if (c == (struct cmd *)-1) {
+                       printf("?Ambiguous command\n");
+                       continue;
+               }
+               if (c == 0) {
+                       printf("?Invalid command\n");
+                       continue;
+               }
+               (*c->handler)(margc, margv);
+       }
+}
+
+struct cmd *
+getcmd(name)
+       register char *name;
+{
+       register char *p, *q;
+       register struct cmd *c, *found;
+       register int nmatches, longest;
+
+       longest = 0;
+       nmatches = 0;
+       found = 0;
+       for (c = cmdtab; (p = c->name) != NULL; c++) {
+               for (q = name; *q == *p++; q++)
+                       if (*q == 0)            /* exact match? */
+                               return (c);
+               if (!*q) {                      /* the name was a prefix */
+                       if (q - name > longest) {
+                               longest = q - name;
+                               nmatches = 1;
+                               found = c;
+                       } else if (q - name == longest)
+                               nmatches++;
+               }
+       }
+       if (nmatches > 1)
+               return ((struct cmd *)-1);
+       return (found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+static void
+makeargv()
+{
+       register char *cp;
+       register char **argp = margv;
+
+       margc = 0;
+       for (cp = line; *cp;) {
+               while (isspace(*cp))
+                       cp++;
+               if (*cp == '\0')
+                       break;
+               *argp++ = cp;
+               margc += 1;
+               while (*cp != '\0' && !isspace(*cp))
+                       cp++;
+               if (*cp == '\0')
+                       break;
+               *cp++ = '\0';
+       }
+       *argp++ = 0;
+}
+
+void
+quit(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       exit(0);
+}
+
+/*
+ * Help command.
+ */
+void
+help(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct cmd *c;
+
+       if (argc == 1) {
+               printf("Commands may be abbreviated.  Commands are:\n\n");
+               for (c = cmdtab; c->name; c++)
+                       printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
+               return;
+       }
+       while (--argc > 0) {
+               register char *arg;
+               arg = *++argv;
+               c = getcmd(arg);
+               if (c == (struct cmd *)-1)
+                       printf("?Ambiguous help command %s\n", arg);
+               else if (c == (struct cmd *)0)
+                       printf("?Invalid help command %s\n", arg);
+               else
+                       printf("%s\n", c->help);
+       }
+}
+
+void
+settrace(argc, argv)
+       int argc;
+       char **argv;
+{
+       trace = !trace;
+       printf("Packet tracing %s.\n", trace ? "on" : "off");
+}
+
+void
+setverbose(argc, argv)
+       int argc;
+       char **argv;
+{
+       verbose = !verbose;
+       printf("Verbose mode %s.\n", verbose ? "on" : "off");
+}
diff --git a/tftp.tproj/tftp.1 b/tftp.tproj/tftp.1
new file mode 100644 (file)
index 0000000..b2c5a16
--- /dev/null
@@ -0,0 +1,173 @@
+.\" Copyright (c) 1990, 1993, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)tftp.1     8.2 (Berkeley) 4/18/94
+.\"
+.Dd April 18, 1994
+.Dt TFTP 1
+.Os BSD 4.3
+.Sh NAME
+.Nm tftp
+.Nd trivial file transfer program
+.Sh SYNOPSIS
+.Nm tftp
+.Op Ar host
+.Sh DESCRIPTION
+.Nm Tftp
+is the user interface to the Internet
+.Tn TFTP
+(Trivial File Transfer Protocol),
+which allows users to transfer files to and from a remote machine.
+The remote
+.Ar host
+may be specified on the command line, in which case
+.Nm tftp
+uses
+.Ar host
+as the default host for future transfers (see the
+.Cm connect
+command below).
+.Sh COMMANDS
+Once
+.Nm tftp
+is running, it issues the prompt
+.LI tftp>
+and recognizes the following commands:
+.Pp
+.Bl -tag -width verbose -compact
+.It Cm \&? Ar command-name ...
+Print help information.
+.Pp
+.It Cm ascii
+Shorthand for "mode ascii"
+.Pp
+.It Cm binary
+Shorthand for "mode binary"
+.Pp
+.It Cm connect Ar host-name Op Ar port
+Set the
+.Ar host
+(and optionally
+.Ar port )
+for transfers.
+Note that the
+.Tn TFTP
+protocol, unlike the
+.Tn FTP
+protocol,
+does not maintain connections between transfers; thus, the
+.Cm connect
+command does not actually create a connection,
+but merely remembers what host is to be used for transfers.
+You do not have to use the 
+.Cm connect
+command; the remote host can be specified as part of the
+.Cm get
+or
+.Cm put
+commands.
+.Pp
+.It Cm get Ar filename
+.It Cm get Ar remotename localname
+.It Cm get Ar file1 file2 ...  fileN
+Get a file or set of files from the specified
+.Ar sources .
+.Ar Source
+can be in one of two forms:
+a filename on the remote host, if the host has already been specified,
+or a string of the form
+.Ar hosts:filename
+to specify both a host and filename at the same time.
+If the latter form is used,
+the last hostname specified becomes the default for future transfers.
+.Pp
+.It Cm mode Ar transfer-mode
+Set the mode for transfers; 
+.Ar transfer-mode
+may be one of
+.Em ascii
+or
+.Em binary .
+The default is
+.Em ascii .
+.Pp
+.It Cm put Ar file
+.It Cm put Ar localfile remotefile
+.It Cm put Ar file1 file2 ... fileN remote-directory
+Put a file or set of files to the specified
+remote file or directory.
+The destination
+can be in one of two forms:
+a filename on the remote host, if the host has already been specified,
+or a string of the form
+.Ar hosts:filename
+to specify both a host and filename at the same time.
+If the latter form is used,
+the hostname specified becomes the default for future transfers.
+If the remote-directory form is used, the remote host is
+assumed to be a
+.Tn UNIX
+machine.
+.Pp
+.It Cm quit
+Exit
+.Nm tftp .
+An end of file also exits.
+.Pp
+.It Cm rexmt Ar retransmission-timeout
+Set the per-packet retransmission timeout, in seconds.
+.Pp
+.It Cm status
+Show current status.
+.Pp
+.It Cm timeout Ar total-transmission-timeout
+Set the total transmission timeout, in seconds.
+.Pp
+.It Cm trace
+Toggle packet tracing.
+.Pp
+.It Cm verbose
+Toggle verbose mode.
+.El
+.Sh BUGS
+.Pp
+Because there is no user-login or validation within
+the
+.Tn TFTP
+protocol, the remote site will probably have some
+sort of file-access restrictions in place.  The
+exact methods are specific to each site and therefore
+difficult to document here.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/tftp.tproj/tftp.c b/tftp.tproj/tftp.c
new file mode 100644 (file)
index 0000000..bec2978
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
+
+/*
+ * TFTP User Program -- Protocol Machines
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#include <arpa/tftp.h>
+
+#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "extern.h"
+#include "tftpsubs.h"
+
+extern int errno;
+
+extern  struct sockaddr_in peeraddr;   /* filled in by main */
+extern  int     f;                     /* the opened socket */
+extern  int     trace;
+extern  int     verbose;
+extern  int     rexmtval;
+extern  int     maxtimeout;
+
+extern jmp_buf toplevel;       /* filled in by main */
+
+#define PKTSIZE    SEGSIZE+4
+char    ackbuf[PKTSIZE];
+int    timeout;
+jmp_buf        timeoutbuf;
+
+static void nak __P((int));
+static int makerequest __P((int, const char *, struct tftphdr *, const char *));
+static void printstats __P((const char *, unsigned long));
+static void startclock __P((void));
+static void stopclock __P((void));
+static void timer __P((int));
+static void tpacket __P((const char *, struct tftphdr *, int));
+
+/*
+ * Send the requested file.
+ */
+void
+tftp_sendfile(fd, name, mode)
+       int fd;
+       char *name;
+       char *mode;
+{
+       register struct tftphdr *ap;       /* data and ack packets */
+       struct tftphdr *r_init(), *dp;
+       register int n;
+       volatile int block, size, convert;
+       volatile unsigned long amount;
+       struct sockaddr_in from;
+       int fromlen;
+       FILE *file;
+
+       startclock();           /* start stat's clock */
+       dp = r_init();          /* reset fillbuf/read-ahead code */
+       ap = (struct tftphdr *)ackbuf;
+       file = fdopen(fd, "r");
+       convert = !strcmp(mode, "netascii");
+       block = 0;
+       amount = 0;
+
+       signal(SIGALRM, timer);
+       do {
+               if (block == 0)
+                       size = makerequest(WRQ, name, dp, mode) - 4;
+               else {
+               /*      size = read(fd, dp->th_data, SEGSIZE);   */
+                       size = readit(file, &dp, convert);
+                       if (size < 0) {
+                               nak(errno + 100);
+                               break;
+                       }
+                       dp->th_opcode = htons((u_short)DATA);
+                       dp->th_block = htons((u_short)block);
+               }
+               timeout = 0;
+               (void) setjmp(timeoutbuf);
+send_data:
+               if (trace)
+                       tpacket("sent", dp, size + 4);
+               n = sendto(f, dp, size + 4, 0,
+                   (struct sockaddr *)&peeraddr, sizeof(peeraddr));
+               if (n != size + 4) {
+                       perror("tftp: sendto");
+                       goto abort;
+               }
+               read_ahead(file, convert);
+               for ( ; ; ) {
+                       alarm(rexmtval);
+                       do {
+                               fromlen = sizeof(from);
+                               n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
+                                   (struct sockaddr *)&from, &fromlen);
+                       } while (n <= 0);
+                       alarm(0);
+                       if (n < 0) {
+                               perror("tftp: recvfrom");
+                               goto abort;
+                       }
+                       peeraddr.sin_port = from.sin_port;      /* added */
+                       if (trace)
+                               tpacket("received", ap, n);
+                       /* should verify packet came from server */
+                       ap->th_opcode = ntohs(ap->th_opcode);
+                       ap->th_block = ntohs(ap->th_block);
+                       if (ap->th_opcode == ERROR) {
+                               printf("Error code %d: %s\n", ap->th_code,
+                                       ap->th_msg);
+                               goto abort;
+                       }
+                       if (ap->th_opcode == ACK) {
+                               int j;
+
+                               if (ap->th_block == block) {
+                                       break;
+                               }
+                               /* On an error, try to synchronize
+                                * both sides.
+                                */
+                               j = synchnet(f);
+                               if (j && trace) {
+                                       printf("discarded %d packets\n",
+                                                       j);
+                               }
+                               if (ap->th_block == (block-1)) {
+                                       goto send_data;
+                               }
+                       }
+               }
+               if (block > 0)
+                       amount += size;
+               block++;
+       } while (size == SEGSIZE || block == 1);
+abort:
+       fclose(file);
+       stopclock();
+       if (amount > 0)
+               printstats("Sent", amount);
+}
+
+/*
+ * Receive a file.
+ */
+void
+recvfile(fd, name, mode)
+       int fd;
+       char *name;
+       char *mode;
+{
+       register struct tftphdr *ap;
+       struct tftphdr *dp, *w_init();
+       register int n;
+       volatile int block, size, firsttrip;
+       volatile unsigned long amount;
+       struct sockaddr_in from;
+       int fromlen;
+       FILE *file;
+       volatile int convert;           /* true if converting crlf -> lf */
+
+       startclock();
+       dp = w_init();
+       ap = (struct tftphdr *)ackbuf;
+       file = fdopen(fd, "w");
+       convert = !strcmp(mode, "netascii");
+       block = 1;
+       firsttrip = 1;
+       amount = 0;
+
+       signal(SIGALRM, timer);
+       do {
+               if (firsttrip) {
+                       size = makerequest(RRQ, name, ap, mode);
+                       firsttrip = 0;
+               } else {
+                       ap->th_opcode = htons((u_short)ACK);
+                       ap->th_block = htons((u_short)(block));
+                       size = 4;
+                       block++;
+               }
+               timeout = 0;
+               (void) setjmp(timeoutbuf);
+send_ack:
+               if (trace)
+                       tpacket("sent", ap, size);
+               if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peeraddr,
+                   sizeof(peeraddr)) != size) {
+                       alarm(0);
+                       perror("tftp: sendto");
+                       goto abort;
+               }
+               write_behind(file, convert);
+               for ( ; ; ) {
+                       alarm(rexmtval);
+                       do  {
+                               fromlen = sizeof(from);
+                               n = recvfrom(f, dp, PKTSIZE, 0,
+                                   (struct sockaddr *)&from, &fromlen);
+                       } while (n <= 0);
+                       alarm(0);
+                       if (n < 0) {
+                               perror("tftp: recvfrom");
+                               goto abort;
+                       }
+                       peeraddr.sin_port = from.sin_port;      /* added */
+                       if (trace)
+                               tpacket("received", dp, n);
+                       /* should verify client address */
+                       dp->th_opcode = ntohs(dp->th_opcode);
+                       dp->th_block = ntohs(dp->th_block);
+                       if (dp->th_opcode == ERROR) {
+                               printf("Error code %d: %s\n", dp->th_code,
+                                       dp->th_msg);
+                               goto abort;
+                       }
+                       if (dp->th_opcode == DATA) {
+                               int j;
+
+                               if (dp->th_block == block) {
+                                       break;          /* have next packet */
+                               }
+                               /* On an error, try to synchronize
+                                * both sides.
+                                */
+                               j = synchnet(f);
+                               if (j && trace) {
+                                       printf("discarded %d packets\n", j);
+                               }
+                               if (dp->th_block == (block-1)) {
+                                       goto send_ack;  /* resend ack */
+                               }
+                       }
+               }
+       /*      size = write(fd, dp->th_data, n - 4); */
+               size = writeit(file, &dp, n - 4, convert);
+               if (size < 0) {
+                       nak(errno + 100);
+                       break;
+               }
+               amount += size;
+       } while (size == SEGSIZE);
+abort:                                         /* ok to ack, since user */
+       ap->th_opcode = htons((u_short)ACK);    /* has seen err msg */
+       ap->th_block = htons((u_short)block);
+       (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peeraddr,
+           sizeof(peeraddr));
+       write_behind(file, convert);            /* flush last buffer */
+       fclose(file);
+       stopclock();
+       if (amount > 0)
+               printstats("Received", amount);
+}
+
+static int
+makerequest(request, name, tp, mode)
+       int request;
+       const char *name;
+       struct tftphdr *tp;
+       const char *mode;
+{
+       register char *cp;
+
+       tp->th_opcode = htons((u_short)request);
+       cp = tp->th_stuff;
+       strcpy(cp, name);
+       cp += strlen(name);
+       *cp++ = '\0';
+       strcpy(cp, mode);
+       cp += strlen(mode);
+       *cp++ = '\0';
+       return (cp - (char *)tp);
+}
+
+struct errmsg {
+       int     e_code;
+       char    *e_msg;
+} errmsgs[] = {
+       { EUNDEF,       "Undefined error code" },
+       { ENOTFOUND,    "File not found" },
+       { EACCESS,      "Access violation" },
+       { ENOSPACE,     "Disk full or allocation exceeded" },
+       { EBADOP,       "Illegal TFTP operation" },
+       { EBADID,       "Unknown transfer ID" },
+       { EEXISTS,      "File already exists" },
+       { ENOUSER,      "No such user" },
+       { -1,           0 }
+};
+
+/*
+ * Send a nak packet (error message).
+ * Error code passed in is one of the
+ * standard TFTP codes, or a UNIX errno
+ * offset by 100.
+ */
+static void
+nak(error)
+       int error;
+{
+       register struct errmsg *pe;
+       register struct tftphdr *tp;
+       int length;
+       char *strerror();
+
+       tp = (struct tftphdr *)ackbuf;
+       tp->th_opcode = htons((u_short)ERROR);
+       tp->th_code = htons((u_short)error);
+       for (pe = errmsgs; pe->e_code >= 0; pe++)
+               if (pe->e_code == error)
+                       break;
+       if (pe->e_code < 0) {
+               pe->e_msg = strerror(error - 100);
+               tp->th_code = EUNDEF;
+       }
+       strcpy(tp->th_msg, pe->e_msg);
+       length = strlen(pe->e_msg) + 4;
+       if (trace)
+               tpacket("sent", tp, length);
+       if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&peeraddr,
+           sizeof(peeraddr)) != length)
+               perror("nak");
+}
+
+static void
+tpacket(s, tp, n)
+       const char *s;
+       struct tftphdr *tp;
+       int n;
+{
+       static char *opcodes[] =
+          { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR" };
+       register char *cp, *file;
+       u_short op = ntohs(tp->th_opcode);
+       char *index();
+
+       if (op < RRQ || op > ERROR)
+               printf("%s opcode=%x ", s, op);
+       else
+               printf("%s %s ", s, opcodes[op]);
+       switch (op) {
+
+       case RRQ:
+       case WRQ:
+               n -= 2;
+               file = cp = tp->th_stuff;
+               cp = index(cp, '\0');
+               printf("<file=%s, mode=%s>\n", file, cp + 1);
+               break;
+
+       case DATA:
+               printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);
+               break;
+
+       case ACK:
+               printf("<block=%d>\n", ntohs(tp->th_block));
+               break;
+
+       case ERROR:
+               printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);
+               break;
+       }
+}
+
+struct timeval tstart;
+struct timeval tstop;
+
+static void
+startclock()
+{
+
+       (void)gettimeofday(&tstart, NULL);
+}
+
+static void
+stopclock()
+{
+
+       (void)gettimeofday(&tstop, NULL);
+}
+
+static void
+printstats(direction, amount)
+       const char *direction;
+       unsigned long amount;
+{
+       double delta;
+                       /* compute delta in 1/10's second units */
+       delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) -
+               ((tstart.tv_sec*10.)+(tstart.tv_usec/100000));
+       delta = delta/10.;      /* back to seconds */
+       printf("%s %d bytes in %.1f seconds", direction, amount, delta);
+       if (verbose)
+               printf(" [%.0f bits/sec]", (amount*8.)/delta);
+       putchar('\n');
+}
+
+static void
+timer(sig)
+       int sig;
+{
+
+       timeout += rexmtval;
+       if (timeout >= maxtimeout) {
+               printf("Transfer timed out.\n");
+               longjmp(toplevel, -1);
+       }
+       longjmp(timeoutbuf, 1);
+}
diff --git a/tftp.tproj/tftpsubs.c b/tftp.tproj/tftpsubs.c
new file mode 100644 (file)
index 0000000..f63504a
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/* Simple minded read-ahead/write-behind subroutines for tftp user and
+   server.  Written originally with multiple buffers in mind, but current
+   implementation has two buffer logic wired in.
+
+   Todo:  add some sort of final error check so when the write-buffer
+   is finally flushed, the caller can detect if the disk filled up
+   (or had an i/o error) and return a nak to the other side.
+
+                       Jim Guyton 10/85
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/tftp.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "tftpsubs.h"
+
+#define PKTSIZE SEGSIZE+4       /* should be moved to tftp.h */
+
+struct bf {
+       int counter;            /* size of data in buffer, or flag */
+       char buf[PKTSIZE];      /* room for data packet */
+} bfs[2];
+
+                               /* Values for bf.counter  */
+#define BF_ALLOC -3             /* alloc'd but not yet filled */
+#define BF_FREE  -2             /* free */
+/* [-1 .. SEGSIZE] = size of data in the data buffer */
+
+static int nextone;            /* index of next buffer to use */
+static int current;            /* index of buffer in use */
+
+                               /* control flags for crlf conversions */
+int newline = 0;               /* fillbuf: in middle of newline expansion */
+int prevchar = -1;             /* putbuf: previous char (cr check) */
+
+static struct tftphdr *rw_init();
+
+struct tftphdr *w_init() { return rw_init(0); }         /* write-behind */
+struct tftphdr *r_init() { return rw_init(1); }         /* read-ahead */
+
+static struct tftphdr *
+rw_init(x)                     /* init for either read-ahead or write-behind */
+       int x;                  /* zero for write-behind, one for read-head */
+{
+       newline = 0;            /* init crlf flag */
+       prevchar = -1;
+       bfs[0].counter =  BF_ALLOC;     /* pass out the first buffer */
+       current = 0;
+       bfs[1].counter = BF_FREE;
+       nextone = x;                    /* ahead or behind? */
+       return (struct tftphdr *)bfs[0].buf;
+}
+
+
+/* Have emptied current buffer by sending to net and getting ack.
+   Free it and return next buffer filled with data.
+ */
+int
+readit(file, dpp, convert)
+       FILE *file;                     /* file opened for read */
+       struct tftphdr **dpp;
+       int convert;                    /* if true, convert to ascii */
+{
+       struct bf *b;
+
+       bfs[current].counter = BF_FREE; /* free old one */
+       current = !current;             /* "incr" current */
+
+       b = &bfs[current];              /* look at new buffer */
+       if (b->counter == BF_FREE)      /* if it's empty */
+               read_ahead(file, convert);      /* fill it */
+/*      assert(b->counter != BF_FREE);*//* check */
+       *dpp = (struct tftphdr *)b->buf;        /* set caller's ptr */
+       return b->counter;
+}
+
+/*
+ * fill the input buffer, doing ascii conversions if requested
+ * conversions are  lf -> cr,lf  and cr -> cr, nul
+ */
+void
+read_ahead(file, convert)
+       FILE *file;                     /* file opened for read */
+       int convert;                    /* if true, convert to ascii */
+{
+       register int i;
+       register char *p;
+       register int c;
+       struct bf *b;
+       struct tftphdr *dp;
+
+       b = &bfs[nextone];              /* look at "next" buffer */
+       if (b->counter != BF_FREE)      /* nop if not free */
+               return;
+       nextone = !nextone;             /* "incr" next buffer ptr */
+
+       dp = (struct tftphdr *)b->buf;
+
+       if (convert == 0) {
+               b->counter = read(fileno(file), dp->th_data, SEGSIZE);
+               return;
+       }
+
+       p = dp->th_data;
+       for (i = 0 ; i < SEGSIZE; i++) {
+               if (newline) {
+                       if (prevchar == '\n')
+                               c = '\n';       /* lf to cr,lf */
+                       else    c = '\0';       /* cr to cr,nul */
+                       newline = 0;
+               }
+               else {
+                       c = getc(file);
+                       if (c == EOF) break;
+                       if (c == '\n' || c == '\r') {
+                               prevchar = c;
+                               c = '\r';
+                               newline = 1;
+                       }
+               }
+              *p++ = c;
+       }
+       b->counter = (int)(p - dp->th_data);
+}
+
+/* Update count associated with the buffer, get new buffer
+   from the queue.  Calls write_behind only if next buffer not
+   available.
+ */
+int
+writeit(file, dpp, ct, convert)
+       FILE *file;
+       struct tftphdr **dpp;
+       int ct, convert;
+{
+       bfs[current].counter = ct;      /* set size of data to write */
+       current = !current;             /* switch to other buffer */
+       if (bfs[current].counter != BF_FREE)     /* if not free */
+               (void)write_behind(file, convert); /* flush it */
+       bfs[current].counter = BF_ALLOC;        /* mark as alloc'd */
+       *dpp =  (struct tftphdr *)bfs[current].buf;
+       return ct;                      /* this is a lie of course */
+}
+
+/*
+ * Output a buffer to a file, converting from netascii if requested.
+ * CR,NUL -> CR  and CR,LF => LF.
+ * Note spec is undefined if we get CR as last byte of file or a
+ * CR followed by anything else.  In this case we leave it alone.
+ */
+int
+write_behind(file, convert)
+       FILE *file;
+       int convert;
+{
+       char *buf;
+       int count;
+       register int ct;
+       register char *p;
+       register int c;                 /* current character */
+       struct bf *b;
+       struct tftphdr *dp;
+
+       b = &bfs[nextone];
+       if (b->counter < -1)            /* anything to flush? */
+               return 0;               /* just nop if nothing to do */
+
+       count = b->counter;             /* remember byte count */
+       b->counter = BF_FREE;           /* reset flag */
+       dp = (struct tftphdr *)b->buf;
+       nextone = !nextone;             /* incr for next time */
+       buf = dp->th_data;
+
+       if (count <= 0) return -1;      /* nak logic? */
+
+       if (convert == 0)
+               return write(fileno(file), buf, count);
+
+       p = buf;
+       ct = count;
+       while (ct--) {                  /* loop over the buffer */
+           c = *p++;                   /* pick up a character */
+           if (prevchar == '\r') {     /* if prev char was cr */
+               if (c == '\n')          /* if have cr,lf then just */
+                  fseek(file, -1, 1);  /* smash lf on top of the cr */
+               else
+                  if (c == '\0')       /* if have cr,nul then */
+                       goto skipit;    /* just skip over the putc */
+               /* else just fall through and allow it */
+           }
+           putc(c, file);
+skipit:
+           prevchar = c;
+       }
+       return count;
+}
+
+
+/* When an error has occurred, it is possible that the two sides
+ * are out of synch.  Ie: that what I think is the other side's
+ * response to packet N is really their response to packet N-1.
+ *
+ * So, to try to prevent that, we flush all the input queued up
+ * for us on the network connection on our host.
+ *
+ * We return the number of packets we flushed (mostly for reporting
+ * when trace is active).
+ */
+
+int
+synchnet(f)
+       int     f;              /* socket to flush */
+{
+       int i, j = 0;
+       char rbuf[PKTSIZE];
+       struct sockaddr_in from;
+       int fromlen;
+
+       while (1) {
+               (void) ioctl(f, FIONREAD, &i);
+               if (i) {
+                       j++;
+                       fromlen = sizeof from;
+                       (void) recvfrom(f, rbuf, sizeof (rbuf), 0,
+                               (struct sockaddr *)&from, &fromlen);
+               } else {
+                       return(j);
+               }
+       }
+}
diff --git a/tftp.tproj/tftpsubs.h b/tftp.tproj/tftpsubs.h
new file mode 100644 (file)
index 0000000..9ecb2d2
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)tftpsubs.h  8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Prototypes for read-ahead/write-behind subroutines for tftp user and
+ * server.
+ */
+struct tftphdr *r_init __P((void));
+void   read_ahead __P((FILE *, int));
+int    readit __P((FILE *, struct tftphdr **, int));
+
+int    synchnet __P((int));
+
+struct tftphdr *w_init __P((void));
+int    write_behind __P((FILE *, int));
+int    writeit __P((FILE *, struct tftphdr **, int, int));
diff --git a/tftpd.tproj/Makefile b/tftpd.tproj/Makefile
new file mode 100644 (file)
index 0000000..8ce74c9
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = tftpd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = tftpd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble tftpd.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS = -I../tftp.tproj
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/tftpd.tproj/Makefile.postamble b/tftpd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..382a280
--- /dev/null
@@ -0,0 +1,112 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
+VPATH += :../tftp.tproj
diff --git a/tftpd.tproj/Makefile.preamble b/tftpd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..8a2e16a
--- /dev/null
@@ -0,0 +1,121 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+OTHER_OFILES = tftpsubs.o
+
+-include ../Makefile.include
diff --git a/tftpd.tproj/PB.project b/tftpd.tproj/PB.project
new file mode 100644 (file)
index 0000000..39cfa7e
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        HEADERSEARCH = (../tftp.tproj); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (tftpd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, tftpd.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = tftpd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/tftpd.tproj/tftpd.8 b/tftpd.tproj/tftpd.8
new file mode 100644 (file)
index 0000000..430c1c4
--- /dev/null
@@ -0,0 +1,106 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)tftpd.8     8.1 (Berkeley) 6/4/93
+.\"
+.Dd June 4, 1993
+.Dt TFTPD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm tftpd
+.Nd
+Internet Trivial File Transfer Protocol server
+.Sh SYNOPSIS
+.Nm tftpd
+.Op Fl l
+.Op Fl n
+.Op Ar directory ...
+.Sh DESCRIPTION
+.Nm Tftpd
+is a server which supports the
+Internet Trivial File Transfer
+Protocol (\c
+.Tn RFC 783).
+The
+.Tn TFTP
+server operates
+at the port indicated in the
+.Ql tftp
+service description;
+see
+.Xr services 5 .
+The server is normally started by
+.Xr inetd 8 .
+.Pp
+The use of
+.Xr tftp 1
+does not require an account or password on the remote system.
+Due to the lack of authentication information, 
+.Nm tftpd
+will allow only publicly readable files to be
+accessed.
+Files containing the string ``/\|\fB.\|.\fP\|/'' are not allowed.
+Files may be written only if they already exist and are publicly writable.
+Note that this extends the concept of
+.Dq public
+to include
+all users on all hosts that can be reached through the network;
+this may not be appropriate on all systems, and its implications
+should be considered before enabling tftp service.
+The server should have the user ID with the lowest possible privilege.
+.Pp
+Access to files may be restricted by invoking
+.Nm tftpd
+with a list of directories by including up to 20 pathnames
+as server program arguments in
+.Pa /etc/inetd.conf .
+In this case access is restricted to files whose
+names are prefixed by the one of the given directories.
+The given directories are also treated as a search path for 
+relative filename requests.
+.Pp
+The options are:
+.Bl -tag -width Ds
+.It Fl l
+Logs all requests using
+.Xr syslog 3 .
+.It Fl n
+Suppresses negative acknowledgement of requests for nonexistent
+relative filenames.
+.El
+.Sh SEE ALSO
+.Xr tftp 1 ,
+.Xr inetd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/tftpd.tproj/tftpd.c b/tftpd.tproj/tftpd.c
new file mode 100644 (file)
index 0000000..f73cb56
--- /dev/null
@@ -0,0 +1,673 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tftpd.c    8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * Trivial file transfer protocol server.
+ *
+ * This version includes many modifications by Jim Guyton
+ * <guyton@rand-unix>.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/tftp.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "tftpsubs.h"
+
+#define        TIMEOUT         5
+
+int    peer;
+int    rexmtval = TIMEOUT;
+int    maxtimeout = 5*TIMEOUT;
+
+#define        PKTSIZE SEGSIZE+4
+char   buf[PKTSIZE];
+char   ackbuf[PKTSIZE];
+struct sockaddr_in from;
+int    fromlen;
+
+void   tftp __P((struct tftphdr *, int));
+
+/*
+ * Null-terminated directory prefix list for absolute pathname requests and
+ * search list for relative pathname requests.
+ *
+ * MAXDIRS should be at least as large as the number of arguments that
+ * inetd allows (currently 20).
+ */
+#define MAXDIRS        20
+static struct dirlist {
+       char    *name;
+       int     len;
+} dirs[MAXDIRS+1];
+static int     suppress_naks;
+static int     logging;
+
+static char *errtomsg __P((int));
+static void  nak __P((int));
+static char *verifyhost __P((struct sockaddr_in *));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct tftphdr *tp;
+       register int n;
+       int ch, on;
+       struct sockaddr_in sin;
+
+       openlog("tftpd", LOG_PID, LOG_FTP);
+       while ((ch = getopt(argc, argv, "ln")) != EOF) {
+               switch (ch) {
+               case 'l':
+                       logging = 1;
+                       break;
+               case 'n':
+                       suppress_naks = 1;
+                       break;
+               default:
+                       syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
+               }
+       }
+       if (optind < argc) {
+               struct dirlist *dirp;
+
+               /* Get list of directory prefixes. Skip relative pathnames. */
+               for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS];
+                    optind++) {
+                       if (argv[optind][0] == '/') {
+                               dirp->name = argv[optind];
+                               dirp->len  = strlen(dirp->name);
+                               dirp++;
+                       }
+               }
+       }
+
+       on = 1;
+       if (ioctl(0, FIONBIO, &on) < 0) {
+               syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
+               exit(1);
+       }
+       fromlen = sizeof (from);
+       n = recvfrom(0, buf, sizeof (buf), 0,
+           (struct sockaddr *)&from, &fromlen);
+       if (n < 0) {
+               syslog(LOG_ERR, "recvfrom: %m\n");
+               exit(1);
+       }
+       /*
+        * Now that we have read the message out of the UDP
+        * socket, we fork and exit.  Thus, inetd will go back
+        * to listening to the tftp port, and the next request
+        * to come in will start up a new instance of tftpd.
+        *
+        * We do this so that inetd can run tftpd in "wait" mode.
+        * The problem with tftpd running in "nowait" mode is that
+        * inetd may get one or more successful "selects" on the
+        * tftp port before we do our receive, so more than one
+        * instance of tftpd may be started up.  Worse, if tftpd
+        * break before doing the above "recvfrom", inetd would
+        * spawn endless instances, clogging the system.
+        */
+       {
+               int pid;
+               int i, j;
+
+               for (i = 1; i < 20; i++) {
+                   pid = fork();
+                   if (pid < 0) {
+                               sleep(i);
+                               /*
+                                * flush out to most recently sent request.
+                                *
+                                * This may drop some request, but those
+                                * will be resent by the clients when
+                                * they timeout.  The positive effect of
+                                * this flush is to (try to) prevent more
+                                * than one tftpd being started up to service
+                                * a single request from a single client.
+                                */
+                               j = sizeof from;
+                               i = recvfrom(0, buf, sizeof (buf), 0,
+                                   (struct sockaddr *)&from, &j);
+                               if (i > 0) {
+                                       n = i;
+                                       fromlen = j;
+                               }
+                   } else {
+                               break;
+                   }
+               }
+               if (pid < 0) {
+                       syslog(LOG_ERR, "fork: %m\n");
+                       exit(1);
+               } else if (pid != 0) {
+                       exit(0);
+               }
+       }
+       from.sin_family = AF_INET;
+       alarm(0);
+       close(0);
+       close(1);
+       peer = socket(AF_INET, SOCK_DGRAM, 0);
+       if (peer < 0) {
+               syslog(LOG_ERR, "socket: %m\n");
+               exit(1);
+       }
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
+               syslog(LOG_ERR, "bind: %m\n");
+               exit(1);
+       }
+       if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {
+               syslog(LOG_ERR, "connect: %m\n");
+               exit(1);
+       }
+       tp = (struct tftphdr *)buf;
+       tp->th_opcode = ntohs(tp->th_opcode);
+       if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
+               tftp(tp, n);
+       exit(1);
+}
+
+struct formats;
+int    validate_access __P((char **, int));
+void   tftp_sendfile __P((struct formats *));
+void   recvfile __P((struct formats *));
+
+struct formats {
+       char    *f_mode;
+       int     (*f_validate) __P((char **, int));
+       void    (*f_send) __P((struct formats *));
+       void    (*f_recv) __P((struct formats *));
+       int     f_convert;
+} formats[] = {
+       { "netascii",   validate_access,        tftp_sendfile,  recvfile, 1 },
+       { "octet",      validate_access,        tftp_sendfile,  recvfile, 0 },
+#ifdef notdef
+       { "mail",       validate_user,          sendmail,       recvmail, 1 },
+#endif
+       { 0 }
+};
+
+/*
+ * Handle initial connection protocol.
+ */
+void
+tftp(tp, size)
+       struct tftphdr *tp;
+       int size;
+{
+       register char *cp;
+       int first = 1, ecode;
+       register struct formats *pf;
+       char *filename, *mode;
+
+       filename = cp = tp->th_stuff;
+again:
+       while (cp < buf + size) {
+               if (*cp == '\0')
+                       break;
+               cp++;
+       }
+       if (*cp != '\0') {
+               nak(EBADOP);
+               exit(1);
+       }
+       if (first) {
+               mode = ++cp;
+               first = 0;
+               goto again;
+       }
+       for (cp = mode; *cp; cp++)
+               if (isupper(*cp))
+                       *cp = tolower(*cp);
+       for (pf = formats; pf->f_mode; pf++)
+               if (strcmp(pf->f_mode, mode) == 0)
+                       break;
+       if (pf->f_mode == 0) {
+               nak(EBADOP);
+               exit(1);
+       }
+       ecode = (*pf->f_validate)(&filename, tp->th_opcode);
+       if (logging) {
+               syslog(LOG_INFO, "%s: %s request for %s: %s",
+                       verifyhost(&from),
+                       tp->th_opcode == WRQ ? "write" : "read",
+                       filename, errtomsg(ecode));
+       }
+       if (ecode) {
+               /*
+                * Avoid storms of naks to a RRQ broadcast for a relative
+                * bootfile pathname from a diskless Sun.
+                */
+               if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
+                       exit(0);
+               nak(ecode);
+               exit(1);
+       }
+       if (tp->th_opcode == WRQ)
+               (*pf->f_recv)(pf);
+       else
+               (*pf->f_send)(pf);
+       exit(0);
+}
+
+
+FILE *file;
+
+/*
+ * Validate file access.  Since we
+ * have no uid or gid, for now require
+ * file to exist and be publicly
+ * readable/writable.
+ * If we were invoked with arguments
+ * from inetd then the file must also be
+ * in one of the given directory prefixes.
+ * Note also, full path name must be
+ * given as we have no login directory.
+ */
+int
+validate_access(filep, mode)
+       char **filep;
+       int mode;
+{
+       struct stat stbuf;
+       int     fd;
+       struct dirlist *dirp;
+       static char pathname[MAXPATHLEN];
+       char *filename = *filep;
+
+       /*
+        * Prevent tricksters from getting around the directory restrictions
+        */
+       if (strstr(filename, "/../"))
+               return (EACCESS);
+
+       if (*filename == '/') {
+               /*
+                * Allow the request if it's in one of the approved locations.
+                * Special case: check the null prefix ("/") by looking
+                * for length = 1 and relying on the arg. processing that
+                * it's a /.
+                */
+               for (dirp = dirs; dirp->name != NULL; dirp++) {
+                       if (dirp->len == 1 ||
+                           (!strncmp(filename, dirp->name, dirp->len) &&
+                            filename[dirp->len] == '/'))
+                                   break;
+               }
+               /* If directory list is empty, allow access to any file */
+               if (dirp->name == NULL && dirp != dirs)
+                       return (EACCESS);
+               if (stat(filename, &stbuf) < 0)
+                       return (errno == ENOENT ? ENOTFOUND : EACCESS);
+               if ((stbuf.st_mode & S_IFMT) != S_IFREG)
+                       return (ENOTFOUND);
+               if (mode == RRQ) {
+                       if ((stbuf.st_mode & S_IROTH) == 0)
+                               return (EACCESS);
+               } else {
+                       if ((stbuf.st_mode & S_IWOTH) == 0)
+                               return (EACCESS);
+               }
+       } else {
+               int err;
+
+               /*
+                * Relative file name: search the approved locations for it.
+                * Don't allow write requests or ones that avoid directory
+                * restrictions.
+                */
+
+               if (mode != RRQ || !strncmp(filename, "../", 3))
+                       return (EACCESS);
+
+               /*
+                * If the file exists in one of the directories and isn't
+                * readable, continue looking. However, change the error code
+                * to give an indication that the file exists.
+                */
+               err = ENOTFOUND;
+               for (dirp = dirs; dirp->name != NULL; dirp++) {
+                       sprintf(pathname, "%s/%s", dirp->name, filename);
+                       if (stat(pathname, &stbuf) == 0 &&
+                           (stbuf.st_mode & S_IFMT) == S_IFREG) {
+                               if ((stbuf.st_mode & S_IROTH) != 0) {
+                                       break;
+                               }
+                               err = EACCESS;
+                       }
+               }
+               if (dirp->name == NULL)
+                       return (err);
+               *filep = filename = pathname;
+       }
+       fd = open(filename, mode == RRQ ? 0 : 1);
+       if (fd < 0)
+               return (errno + 100);
+       file = fdopen(fd, (mode == RRQ)? "r":"w");
+       if (file == NULL) {
+               return errno+100;
+       }
+       return (0);
+}
+
+int    timeout;
+jmp_buf        timeoutbuf;
+
+void
+timer()
+{
+
+       timeout += rexmtval;
+       if (timeout >= maxtimeout)
+               exit(1);
+       longjmp(timeoutbuf, 1);
+}
+
+/*
+ * Send the requested file.
+ */
+void
+tftp_sendfile(pf)
+       struct formats *pf;
+{
+       struct tftphdr *dp, *r_init();
+       register struct tftphdr *ap;    /* ack packet */
+       register int size, n;
+       volatile int block;
+
+       signal(SIGALRM, timer);
+       dp = r_init();
+       ap = (struct tftphdr *)ackbuf;
+       block = 1;
+       do {
+               size = readit(file, &dp, pf->f_convert);
+               if (size < 0) {
+                       nak(errno + 100);
+                       goto abort;
+               }
+               dp->th_opcode = htons((u_short)DATA);
+               dp->th_block = htons((u_short)block);
+               timeout = 0;
+               (void)setjmp(timeoutbuf);
+
+send_data:
+               if (send(peer, dp, size + 4, 0) != size + 4) {
+                       syslog(LOG_ERR, "tftpd: write: %m\n");
+                       goto abort;
+               }
+               read_ahead(file, pf->f_convert);
+               for ( ; ; ) {
+                       alarm(rexmtval);        /* read the ack */
+                       n = recv(peer, ackbuf, sizeof (ackbuf), 0);
+                       alarm(0);
+                       if (n < 0) {
+                               syslog(LOG_ERR, "tftpd: read: %m\n");
+                               goto abort;
+                       }
+                       ap->th_opcode = ntohs((u_short)ap->th_opcode);
+                       ap->th_block = ntohs((u_short)ap->th_block);
+
+                       if (ap->th_opcode == ERROR)
+                               goto abort;
+
+                       if (ap->th_opcode == ACK) {
+                               if (ap->th_block == block)
+                                       break;
+                               /* Re-synchronize with the other side */
+                               (void) synchnet(peer);
+                               if (ap->th_block == (block -1))
+                                       goto send_data;
+                       }
+
+               }
+               block++;
+       } while (size == SEGSIZE);
+abort:
+       (void) fclose(file);
+}
+
+void
+justquit()
+{
+       exit(0);
+}
+
+
+/*
+ * Receive a file.
+ */
+void
+recvfile(pf)
+       struct formats *pf;
+{
+       struct tftphdr *dp, *w_init();
+       register struct tftphdr *ap;    /* ack buffer */
+       register int n, size;
+       volatile int block;
+
+       signal(SIGALRM, timer);
+       dp = w_init();
+       ap = (struct tftphdr *)ackbuf;
+       block = 0;
+       do {
+               timeout = 0;
+               ap->th_opcode = htons((u_short)ACK);
+               ap->th_block = htons((u_short)block);
+               block++;
+               (void) setjmp(timeoutbuf);
+send_ack:
+               if (send(peer, ackbuf, 4, 0) != 4) {
+                       syslog(LOG_ERR, "tftpd: write: %m\n");
+                       goto abort;
+               }
+               write_behind(file, pf->f_convert);
+               for ( ; ; ) {
+                       alarm(rexmtval);
+                       n = recv(peer, dp, PKTSIZE, 0);
+                       alarm(0);
+                       if (n < 0) {            /* really? */
+                               syslog(LOG_ERR, "tftpd: read: %m\n");
+                               goto abort;
+                       }
+                       dp->th_opcode = ntohs((u_short)dp->th_opcode);
+                       dp->th_block = ntohs((u_short)dp->th_block);
+                       if (dp->th_opcode == ERROR)
+                               goto abort;
+                       if (dp->th_opcode == DATA) {
+                               if (dp->th_block == block) {
+                                       break;   /* normal */
+                               }
+                               /* Re-synchronize with the other side */
+                               (void) synchnet(peer);
+                               if (dp->th_block == (block-1))
+                                       goto send_ack;          /* rexmit */
+                       }
+               }
+               /*  size = write(file, dp->th_data, n - 4); */
+               size = writeit(file, &dp, n - 4, pf->f_convert);
+               if (size != (n-4)) {                    /* ahem */
+                       if (size < 0) nak(errno + 100);
+                       else nak(ENOSPACE);
+                       goto abort;
+               }
+       } while (size == SEGSIZE);
+       write_behind(file, pf->f_convert);
+       (void) fclose(file);            /* close data file */
+
+       ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */
+       ap->th_block = htons((u_short)(block));
+       (void) send(peer, ackbuf, 4, 0);
+
+       signal(SIGALRM, justquit);      /* just quit on timeout */
+       alarm(rexmtval);
+       n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
+       alarm(0);
+       if (n >= 4 &&                   /* if read some data */
+           dp->th_opcode == DATA &&    /* and got a data block */
+           block == dp->th_block) {    /* then my last ack was lost */
+               (void) send(peer, ackbuf, 4, 0);     /* resend final ack */
+       }
+abort:
+       return;
+}
+
+struct errmsg {
+       int     e_code;
+       char    *e_msg;
+} errmsgs[] = {
+       { EUNDEF,       "Undefined error code" },
+       { ENOTFOUND,    "File not found" },
+       { EACCESS,      "Access violation" },
+       { ENOSPACE,     "Disk full or allocation exceeded" },
+       { EBADOP,       "Illegal TFTP operation" },
+       { EBADID,       "Unknown transfer ID" },
+       { EEXISTS,      "File already exists" },
+       { ENOUSER,      "No such user" },
+       { -1,           0 }
+};
+
+static char *
+errtomsg(error)
+       int error;
+{
+       static char buf[20];
+       register struct errmsg *pe;
+       if (error == 0)
+               return "success";
+       for (pe = errmsgs; pe->e_code >= 0; pe++)
+               if (pe->e_code == error)
+                       return pe->e_msg;
+       sprintf(buf, "error %d", error);
+       return buf;
+}
+
+/*
+ * Send a nak packet (error message).
+ * Error code passed in is one of the
+ * standard TFTP codes, or a UNIX errno
+ * offset by 100.
+ */
+static void
+nak(error)
+       int error;
+{
+       register struct tftphdr *tp;
+       int length;
+       register struct errmsg *pe;
+
+       tp = (struct tftphdr *)buf;
+       tp->th_opcode = htons((u_short)ERROR);
+       tp->th_code = htons((u_short)error);
+       for (pe = errmsgs; pe->e_code >= 0; pe++)
+               if (pe->e_code == error)
+                       break;
+       if (pe->e_code < 0) {
+               pe->e_msg = strerror(error - 100);
+               tp->th_code = EUNDEF;   /* set 'undef' errorcode */
+       }
+       strcpy(tp->th_msg, pe->e_msg);
+       length = strlen(pe->e_msg);
+       tp->th_msg[length] = '\0';
+       length += 5;
+       if (send(peer, buf, length, 0) != length)
+               syslog(LOG_ERR, "nak: %m\n");
+}
+
+static char *
+verifyhost(fromp)
+       struct sockaddr_in *fromp;
+{
+       struct hostent *hp;
+
+       hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (fromp->sin_addr),
+                           fromp->sin_family);
+       if (hp)
+               return hp->h_name;
+       else
+               return inet_ntoa(fromp->sin_addr);
+}
diff --git a/timed.tproj/Makefile b/timed.tproj/Makefile
new file mode 100644 (file)
index 0000000..fc8a78d
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = timed
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Aggregate
+
+TOOLS = timed.tproj timedc.tproj
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = aggregate.make
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/timed.tproj/Makefile.postamble b/timed.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..18167b9
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
diff --git a/timed.tproj/Makefile.preamble b/timed.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..cc5c371
--- /dev/null
@@ -0,0 +1,121 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libs to link against
+OTHER_LIBS = 
+# Additional libs to link against when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
diff --git a/timed.tproj/PB.project b/timed.tproj/PB.project
new file mode 100644 (file)
index 0000000..624995d
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    FILESTABLE = {
+        H_FILES = (); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        SUBPROJECTS = (timed.tproj, timedc.tproj); 
+        TOOLS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = timed; 
+    PROJECTTYPE = Aggregate; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/timed.tproj/timed.tproj/Makefile b/timed.tproj/timed.tproj/Makefile
new file mode 100644 (file)
index 0000000..8636bc9
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = timed
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h globals.h pathnames.h
+
+CFILES = acksend.c byteorder.c candidate.c cksum.c correct.c master.c\
+         measure.c networkdelta.c readmsg.c slave.c timed.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble timed.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/timed.tproj/timed.tproj/Makefile.postamble b/timed.tproj/timed.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..36381d4
--- /dev/null
@@ -0,0 +1,122 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/timed.tproj/timed.tproj/Makefile.preamble b/timed.tproj/timed.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/timed.tproj/timed.tproj/PB.project b/timed.tproj/timed.tproj/PB.project
new file mode 100644 (file)
index 0000000..e3accbc
--- /dev/null
@@ -0,0 +1,38 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (extern.h, globals.h, pathnames.h); 
+        OTHER_LINKED = (
+            acksend.c, 
+            byteorder.c, 
+            candidate.c, 
+            cksum.c, 
+            correct.c, 
+            master.c, 
+            measure.c, 
+            networkdelta.c, 
+            readmsg.c, 
+            slave.c, 
+            timed.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, timed.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = timed; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/timed.tproj/timed.tproj/acksend.c b/timed.tproj/timed.tproj/acksend.c
new file mode 100644 (file)
index 0000000..af1aea0
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)acksend.c  8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+
+struct tsp *answer;
+
+extern u_short sequence;
+
+void
+xmit(type, seq, addr)
+       int type;
+       u_int seq;
+       struct sockaddr_in *addr;
+{
+       static struct tsp msg;
+
+       msg.tsp_type = type;
+       msg.tsp_seq = seq;
+       msg.tsp_vers = TSPVERSION;
+       (void)strcpy(msg.tsp_name, hostname);
+       bytenetorder(&msg);
+       if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
+                  (struct sockaddr*)addr, sizeof(struct sockaddr)) < 0) {
+               trace_sendto_err(addr->sin_addr);
+       }
+}
+
+
+/*
+ * Acksend implements reliable datagram transmission by using sequence
+ * numbers and retransmission when necessary.
+ * If `name' is ANYADDR, this routine implements reliable broadcast.
+ *
+ * Because this function calls readmsg(), none of its args may be in
+ *     a message provided by readmsg().
+ */
+struct tsp *
+acksend(message, addr, name, ack, net, bad)
+       struct tsp *message;                    /* this message */
+       struct sockaddr_in *addr;               /* to here */
+       char *name;
+       int ack;                                /* look for this ack */
+       struct netinfo *net;                    /* receive from this network */
+       int bad;                                /* 1=losing patience */
+{
+       struct timeval twait;
+       int count;
+       long msec;
+
+       message->tsp_vers = TSPVERSION;
+       message->tsp_seq = sequence;
+       if (trace) {
+               fprintf(fd, "acksend: to %s: ",
+                       (name == ANYADDR ? "broadcast" : name));
+               print(message, addr);
+       }
+       bytenetorder(message);
+
+       msec = 200;
+       count = bad ? 1 : 5;    /* 5 packets in 6.4 seconds */
+       answer = 0;
+       do {
+               if (!answer) {
+                       /* do not go crazy transmitting just because the
+                        * other guy cannot keep our sequence numbers
+                        * straight.
+                        */
+                       if (sendto(sock, (char *)message, sizeof(struct tsp),
+                                  0, (struct sockaddr*)addr,
+                                  sizeof(struct sockaddr)) < 0) {
+                               trace_sendto_err(addr->sin_addr);
+                               break;
+                       }
+               }
+
+               mstotvround(&twait, msec);
+               answer  = readmsg(ack, name, &twait, net);
+               if (answer != 0) {
+                       if (answer->tsp_seq != sequence) {
+                               if (trace)
+                                       fprintf(fd,"acksend: seq # %u!=%u\n",
+                                               answer->tsp_seq, sequence);
+                               continue;
+                       }
+                       break;
+               }
+
+               msec *= 2;
+       } while (--count > 0);
+       sequence++;
+
+       return(answer);
+}
diff --git a/timed.tproj/timed.tproj/byteorder.c b/timed.tproj/timed.tproj/byteorder.c
new file mode 100644 (file)
index 0000000..97bb911
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)byteorder.c        8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+
+/*
+ * Two routines to do the necessary byte swapping for timed protocol
+ * messages. Protocol is defined in /usr/include/protocols/timed.h
+ */
+void
+bytenetorder(ptr)
+       struct tsp *ptr;
+{
+       ptr->tsp_seq = htons((u_short)ptr->tsp_seq);
+       switch (ptr->tsp_type) {
+
+       case TSP_SETTIME:
+       case TSP_ADJTIME:
+       case TSP_SETDATE:
+       case TSP_SETDATEREQ:
+               ptr->tsp_time.tv_sec = htonl((u_long)ptr->tsp_time.tv_sec);
+               ptr->tsp_time.tv_usec = htonl((u_long)ptr->tsp_time.tv_usec);
+               break;
+       
+       default:
+               break;          /* nothing more needed */
+       }
+}
+
+void
+bytehostorder(ptr)
+       struct tsp *ptr;
+{
+       ptr->tsp_seq = ntohs((u_short)ptr->tsp_seq);
+       switch (ptr->tsp_type) {
+
+       case TSP_SETTIME:
+       case TSP_ADJTIME:
+       case TSP_SETDATE:
+       case TSP_SETDATEREQ:
+               ptr->tsp_time.tv_sec = ntohl((u_long)ptr->tsp_time.tv_sec);
+               ptr->tsp_time.tv_usec = ntohl((u_long)ptr->tsp_time.tv_usec);
+               break;
+       
+       default:
+               break;          /* nothing more needed */
+       }
+}
diff --git a/timed.tproj/timed.tproj/candidate.c b/timed.tproj/timed.tproj/candidate.c
new file mode 100644 (file)
index 0000000..a271db5
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)candidate.c        8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+
+/*
+ * `election' candidates a host as master: it is called by a slave
+ * which runs with the -M option set when its election timeout expires.
+ * Note the conservative approach: if a new timed comes up, or another
+ * candidate sends an election request, the candidature is withdrawn.
+ */
+int
+election(net)
+       struct netinfo *net;
+{
+       struct tsp *resp, msg;
+       struct timeval then, wait;
+       struct tsp *answer;
+       struct hosttbl *htp;
+       char loop_lim = 0;
+
+/* This code can get totally confused if it gets slightly behind.  For
+ *     example, if readmsg() has some QUIT messages waiting from the last
+ *     round, we would send an ELECTION message, get the stale QUIT,
+ *     and give up.  This results in network storms when several machines
+ *     do it at once.
+ */
+       wait.tv_sec = 0;
+       wait.tv_usec = 0;
+       while (0 != readmsg(TSP_REFUSE, ANYADDR, &wait, net)) {
+               if (trace)
+                       fprintf(fd, "election: discarded stale REFUSE\n");
+       }
+       while (0 != readmsg(TSP_QUIT, ANYADDR, &wait, net)) {
+               if (trace)
+                       fprintf(fd, "election: discarded stale QUIT\n");
+       }
+
+again:
+       syslog(LOG_INFO, "This machine is a candidate time master");
+       if (trace)
+               fprintf(fd, "This machine is a candidate time master\n");
+       msg.tsp_type = TSP_ELECTION;
+       msg.tsp_vers = TSPVERSION;
+       (void)strcpy(msg.tsp_name, hostname);
+       bytenetorder(&msg);
+       if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
+                  (struct sockaddr*)&net->dest_addr,
+                  sizeof(struct sockaddr)) < 0) {
+               trace_sendto_err(net->dest_addr.sin_addr);
+               return(SLAVE);
+       }
+
+       (void)gettimeofday(&then, 0);
+       then.tv_sec += 3;
+       for (;;) {
+               (void)gettimeofday(&wait, 0);
+               timevalsub(&wait,&then,&wait);
+               resp = readmsg(TSP_ANY, ANYADDR, &wait, net);
+               if (!resp)
+                       return(MASTER);
+
+               switch (resp->tsp_type) {
+
+               case TSP_ACCEPT:
+                       (void)addmach(resp->tsp_name, &from,fromnet);
+                       break;
+
+               case TSP_MASTERUP:
+               case TSP_MASTERREQ:
+                       /*
+                        * If another timedaemon is coming up at the same
+                        * time, give up, and let it be the master.
+                        */
+                       if (++loop_lim < 5
+                           && !good_host_name(resp->tsp_name)) {
+                               (void)addmach(resp->tsp_name, &from,fromnet);
+                               suppress(&from, resp->tsp_name, net);
+                               goto again;
+                       }
+                       rmnetmachs(net);
+                       return(SLAVE);
+
+               case TSP_QUIT:
+               case TSP_REFUSE:
+                       /*
+                        * Collision: change value of election timer
+                        * using exponential backoff. 
+                        *
+                        *  Fooey.
+                        * An exponential backoff on a delay starting at
+                        * 6 to 15 minutes for a process that takes
+                        * milliseconds is silly.  It is particularly
+                        * strange that the original code would increase
+                        * the backoff without bound.
+                        */
+                       rmnetmachs(net);
+                       return(SLAVE);
+
+               case TSP_ELECTION:
+                       /* no master for another round */
+                       htp = addmach(resp->tsp_name,&from,fromnet);
+                       msg.tsp_type = TSP_REFUSE;
+                       (void)strcpy(msg.tsp_name, hostname);
+                       answer = acksend(&msg, &htp->addr, htp->name,
+                                        TSP_ACK, 0, htp->noanswer);
+                       if (!answer) {
+                               syslog(LOG_ERR, "error in election from %s",
+                                      htp->name);
+                       }
+                       break;
+
+               case TSP_SLAVEUP:
+                       (void)addmach(resp->tsp_name, &from,fromnet);
+                       break;
+
+               case TSP_SETDATE:
+               case TSP_SETDATEREQ:
+                       break;
+
+               default:
+                       if (trace) {
+                               fprintf(fd, "candidate: ");
+                               print(resp, &from);
+                       }
+                       break;
+               }
+       }
+}
diff --git a/timed.tproj/timed.tproj/cksum.c b/timed.tproj/timed.tproj/cksum.c
new file mode 100644 (file)
index 0000000..e50e438
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cksum.c    8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include <sys/types.h>
+
+/*
+ *                     I N _ C K S U M
+ *
+ * Checksum routine for Internet Protocol family headers (C Version)
+ *
+ * There is no profit in a specialized version of the checksum
+ * function for any machine where int's are 32 bits and shorts are 16.
+ *
+ * All timed packets are smaller than 32K shorts, so there is no need to
+ * worry about carries except at the end.
+ */
+int
+in_cksum(addr, len)
+       u_short *addr;
+       int len;
+{
+       register int nleft = len;
+       register u_short *w = addr;
+       register u_short answer;
+       register int sum = 0;
+
+       /*
+        *  Our algorithm is simple, using a 32 bit accumulator (sum),
+        *  we add sequential 16 bit words to it, and at the end, fold
+        *  back all the carry bits from the top 16 bits into the lower
+        *  16 bits.
+        */
+       while( nleft > 1 )  {
+               sum += *w++;
+               nleft -= 2;
+       }
+
+       /* mop up an odd byte, if necessary */
+       if( nleft == 1 )
+               sum += (*(u_char *)w) << 8;
+
+       /*
+        * add back carry outs from top 16 bits to low 16 bits
+        */
+       sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
+       sum += (sum >> 16);                     /* add carry */
+       answer = ~sum;                          /* truncate to 16 bits */
+       return (answer);
+}
diff --git a/timed.tproj/timed.tproj/correct.c b/timed.tproj/timed.tproj/correct.c
new file mode 100644 (file)
index 0000000..f092bca
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)correct.c  8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+#include <math.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#ifdef sgi
+#include <sys/syssgi.h>
+#endif /* sgi */
+
+static void adjclock __P((struct timeval *));
+
+/*
+ * sends to the slaves the corrections for their clocks after fixing our
+ * own
+ */
+void
+correct(avdelta)
+       long avdelta;
+{
+       struct hosttbl *htp;
+       int corr;
+       struct timeval adjlocal;
+       struct tsp to;
+       struct tsp *answer;
+
+       mstotvround(&adjlocal, avdelta);
+
+       for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+               if (htp->delta != HOSTDOWN)  {
+                       corr = avdelta - htp->delta;
+/* If the other machine is off in the weeds, set its time directly.
+ *     If a slave gets the wrong day, the original code would simply
+ *     fix the minutes.  If you fix a network partition, you can get
+ *     into such situations.
+ */
+                       if (htp->need_set
+                           || corr >= MAXADJ*1000
+                           || corr <= -MAXADJ*1000) {
+                               htp->need_set = 0;
+                               (void)gettimeofday(&to.tsp_time,0);
+                               timevaladd(&to.tsp_time, &adjlocal);
+                               to.tsp_type = TSP_SETTIME;
+                       } else {
+                               mstotvround(&to.tsp_time, corr);
+                               to.tsp_type = TSP_ADJTIME;
+                       }
+                       (void)strcpy(to.tsp_name, hostname);
+                       answer = acksend(&to, &htp->addr, htp->name,
+                                        TSP_ACK, 0, 0);
+                       if (!answer) {
+                               htp->delta = HOSTDOWN;
+                               syslog(LOG_WARNING,
+                                      "no reply to time correction from %s",
+                                      htp->name);
+                               if (++htp->noanswer >= LOSTHOST) {
+                                       if (trace) {
+                                               fprintf(fd,
+                                            "purging %s for not answering\n",
+                                                       htp->name);
+                                               (void)fflush(fd);
+                                       }
+                                       htp = remmach(htp);
+                               }
+                       }
+               }
+       }
+
+       /*
+        * adjust our own clock now that we are not sending it out
+        */
+       adjclock(&adjlocal);
+}
+
+
+static void
+adjclock(corr)
+       struct timeval *corr;
+{
+       static int passes = 0;
+       static int smoother = 0;
+       long delta;                     /* adjustment in usec */
+       long ndelta;
+       struct timeval now;
+       struct timeval adj;
+
+       if (!timerisset(corr))
+               return;
+
+       adj = *corr;
+       if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) {
+               delta = adj.tv_sec*1000000 + adj.tv_usec;
+               /* If the correction is less than the minimum round
+                *      trip time for an ICMP packet, and thus
+                *      less than the likely error in the measurement,
+                *      do not do the entire correction.  Do half
+                *      or a quarter of it.
+                */
+
+               if (delta > -MIN_ROUND*1000
+                   && delta < MIN_ROUND*1000) {
+                       if (smoother <= 4)
+                               smoother++;
+                       ndelta = delta >> smoother;
+                       if (trace)
+                               fprintf(fd,
+                                       "trimming delta %ld usec to %ld\n",
+                                       delta, ndelta);
+                       adj.tv_usec = ndelta;
+                       adj.tv_sec = 0;
+               } else if (smoother > 0) {
+                       smoother--;
+               }
+               if (0 > adjtime(corr, 0)) {
+                       syslog(LOG_ERR, "adjtime: %m");
+               }
+               if (passes > 1
+                   && (delta < -BIG_ADJ || delta > BIG_ADJ)) {
+                       smoother = 0;
+                       passes = 0;
+                       syslog(LOG_WARNING,
+                              "large time adjustment of %+.3f sec",
+                              delta/1000000.0);
+               }
+       } else {
+               syslog(LOG_WARNING,
+                      "clock correction %d sec too large to adjust",
+                      adj.tv_sec);
+               (void) gettimeofday(&now, 0);
+               timevaladd(&now, corr);
+               if (settimeofday(&now, 0) < 0)
+                       syslog(LOG_ERR, "settimeofday: %m");
+       }
+
+#ifdef sgi
+       /* Accumulate the total change, and use it to adjust the basic
+        * clock rate.
+        */
+       if (++passes > 2) {
+#define F_USEC_PER_SEC (1000000*1.0)   /* reduce typos */
+#define F_NSEC_PER_SEC (F_USEC_PER_SEC*1000.0)
+
+               extern char *timetrim_fn;
+               extern char *timetrim_wpat;
+               extern long timetrim;
+               extern double tot_adj, hr_adj;  /* totals in nsec */
+               extern double tot_ticks, hr_ticks;
+
+               static double nag_tick;
+               double cur_ticks, hr_delta_ticks, tot_delta_ticks;
+               double tru_tot_adj, tru_hr_adj; /* nsecs of adjustment */
+               double tot_trim, hr_trim;   /* nsec/sec */
+               struct tms tm;
+               FILE *timetrim_st;
+
+               cur_ticks = times(&tm);
+               tot_adj += delta*1000.0;
+               hr_adj += delta*1000.0;
+
+               tot_delta_ticks = cur_ticks-tot_ticks;
+               if (tot_delta_ticks >= 16*SECDAY*CLK_TCK) {
+                       tot_adj -= rint(tot_adj/16);
+                       tot_ticks += rint(tot_delta_ticks/16);
+                       tot_delta_ticks = cur_ticks-tot_ticks;
+               }
+               hr_delta_ticks = cur_ticks-hr_ticks;
+
+               tru_hr_adj = hr_adj + timetrim*rint(hr_delta_ticks/CLK_TCK);
+               tru_tot_adj = (tot_adj
+                              + timetrim*rint(tot_delta_ticks/CLK_TCK));
+
+               if (hr_delta_ticks >= SECDAY*CLK_TCK
+                   || (tot_delta_ticks < 4*SECDAY*CLK_TCK
+                       && hr_delta_ticks >= SECHR*CLK_TCK)
+                   || (trace && hr_delta_ticks >= (SECHR/10)*CLK_TCK)) {
+
+                       tot_trim = rint(tru_tot_adj*CLK_TCK/tot_delta_ticks);
+                       hr_trim = rint(tru_hr_adj*CLK_TCK/hr_delta_ticks);
+
+                       if (trace
+                           || (abs(timetrim - hr_trim) > 100000.0
+                               && 0 == timetrim_fn
+                               && ((cur_ticks - nag_tick)
+                                   >= 24*SECDAY*CLK_TCK))) {
+                               nag_tick = cur_ticks;
+                               syslog(LOG_NOTICE,
+                  "%+.3f/%.2f or %+.3f/%.2f sec/hr; timetrim=%+.0f or %+.0f",
+                                      tru_tot_adj/F_NSEC_PER_SEC,
+                                      tot_delta_ticks/(SECHR*CLK_TCK*1.0),
+                                      tru_hr_adj/F_NSEC_PER_SEC,
+                                      hr_delta_ticks/(SECHR*CLK_TCK*1.0),
+                                      tot_trim,
+                                      hr_trim);
+                       }
+
+                       if (tot_trim < -MAX_TRIM || tot_trim > MAX_TRIM) {
+                               tot_ticks = hr_ticks;
+                               tot_adj = hr_adj;
+                       } else if (0 > syssgi(SGI_SETTIMETRIM,
+                                             (long)tot_trim)) {
+                               syslog(LOG_ERR, "SETTIMETRIM(%d): %m",
+                                      (long)tot_trim);
+                       } else {
+                               if (0 != timetrim_fn) {
+                                   timetrim_st = fopen(timetrim_fn, "w");
+                                   if (0 == timetrim_st) {
+                                       syslog(LOG_ERR, "fopen(%s): %m",
+                                              timetrim_fn);
+                                   } else {
+                                       if (0 > fprintf(timetrim_st,
+                                                       timetrim_wpat,
+                                                       (long)tot_trim,
+                                                       tru_tot_adj,
+                                                       tot_delta_ticks)) {
+                                               syslog(LOG_ERR,
+                                                      "fprintf(%s): %m",
+                                                      timetrim_fn);
+                                       }
+                                       (void)fclose(timetrim_st);
+                                   }
+                               }
+
+                               tot_adj -= ((tot_trim - timetrim)
+                                           * rint(tot_delta_ticks/CLK_TCK));
+                               timetrim = tot_trim;
+                       }
+
+                       hr_ticks = cur_ticks;
+                       hr_adj = 0;
+               }
+       }
+#endif /* sgi */
+}
+
+
+/* adjust the time in a message by the time it
+ *     spent in the queue
+ */
+void
+adj_msg_time(msg, now)
+       struct tsp *msg;
+       struct timeval *now;
+{
+       msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec);
+       msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec);
+
+       while (msg->tsp_time.tv_usec < 0) {
+               msg->tsp_time.tv_sec--;
+               msg->tsp_time.tv_usec += 1000000;
+       }
+       while (msg->tsp_time.tv_usec >= 1000000) {
+               msg->tsp_time.tv_sec++;
+               msg->tsp_time.tv_usec -= 1000000;
+       }
+}
diff --git a/timed.tproj/timed.tproj/extern.h b/timed.tproj/timed.tproj/extern.h
new file mode 100644 (file)
index 0000000..00f9d35
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)extern.h    8.1 (Berkeley) 6/6/93
+ */
+
+struct hosttbl;
+struct netinfo;
+struct sockaddr_in;
+struct timeval;
+struct tsp;
+
+struct hosttbl *addmach __P((char *, struct sockaddr_in *, struct netinfo *));
+struct hosttbl *findhost __P((char *));
+struct hosttbl *remmach __P((struct hosttbl *));
+
+struct tsp *readmsg __P((int,
+           char *, struct timeval *, struct netinfo *));
+struct tsp *acksend __P((struct tsp *,
+           struct sockaddr_in *, char *, int, struct netinfo *, int));
+
+void    addnetname __P((char *));
+void    adj_msg_time __P((struct tsp *, struct timeval *));
+void    bytehostorder __P((struct tsp *));
+void    bytenetorder __P((struct tsp *));
+void    byteorder __P((struct tsp *));
+long    casual __P((long, long));
+int     cksum __P((u_short *, int));
+void    correct __P((long));
+char   *date __P((void));
+void    doquit __P((struct tsp *));
+int     election __P((struct netinfo *));
+void    get_goodgroup __P((int));
+int     good_host_name __P((char *));
+void    ignoreack __P((void));
+int     in_cksum __P((u_short *, int));
+void    lookformaster __P((struct netinfo *));
+void    makeslave __P((struct netinfo *));
+int     master __P((void));
+void    masterack __P((void));
+void    masterup __P((struct netinfo *));
+int     measure __P((u_long, u_long, char *, struct sockaddr_in *, int));
+void    msterup __P((struct netinfo *));
+void    mstotvround __P((struct timeval *, long));
+long    networkdelta __P((void));
+void    newslave __P((struct tsp *));
+void    print __P((struct tsp *, struct sockaddr_in *));
+void    prthp __P((clock_t));
+void    rmnetmachs __P((struct netinfo *));
+void    setstatus __P((void));
+int     slave __P((void));
+void    slaveack __P((void));
+void    spreadtime __P((void));
+void    suppress __P((struct sockaddr_in *, char *, struct netinfo *));
+void    synch __P((long));
+void    timevaladd __P((struct timeval *, struct timeval *));
+void    timevalsub __P((struct timeval *, struct timeval *, struct timeval *));
+void    traceoff __P((char *));
+void    traceon __P((void));
+void    xmit __P((int, u_int, struct sockaddr_in *));
diff --git a/timed.tproj/timed.tproj/globals.h b/timed.tproj/timed.tproj/globals.h
new file mode 100644 (file)
index 0000000..82cfc53
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)globals.h   8.1 (Berkeley) 6/6/93
+ */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <protocols/timed.h>
+#ifdef sgi
+#include <bstring.h>
+#include <sys/clock.h>
+/* use the constant HZ instead of the function CLK_TCK */
+#undef CLK_TCK
+#define CLK_TCK HZ
+#else
+#define        SECHR   (60*60)
+#define        SECDAY  (24*SECHR)
+#endif /* sgi */
+
+extern int errno;
+extern int sock;
+
+/* Best expected round trip for a measurement.
+ * This is essentially the number of milliseconds per CPU tick (CLK_TCK?).
+ * All delays shorter than this are usually reported as 0.
+ */
+#define MIN_ROUND ((1000-1)/CLK_TCK)
+
+
+#define SAMPLEINTVL    240             /* synch() freq for master in sec */
+#define        MAXADJ          20              /* max adjtime() correction in sec */
+
+#define MAX_TRIM       3000000         /* max drift in nsec/sec, 0.3% */
+#define BIG_ADJ                (MAX_TRIM/1000*SAMPLEINTVL*2)   /* max good adj */
+
+#define MINTOUT                360             /* election delays, 6-15 minutes */
+#define MAXTOUT                900
+
+#define BAD_STATUS     (-1)
+#define GOOD           1
+#define UNREACHABLE    2
+#define NONSTDTIME     3
+#define HOSTDOWN       0x7fffffff
+
+#define OFF            0
+#define ON             1
+
+#define MAX_HOPCNT     10              /* max value for tsp_hpcnt */
+
+#define LOSTHOST       3               /* forget after this many failures */
+
+#define VALID_RANGE (MAXADJ*1000)      /* good times in milliseconds */
+#define GOOD_RANGE (MIN_ROUND*2)
+#define VGOOD_RANGE (MIN_ROUND-1)
+
+
+/*
+ * Global and per-network states.
+ */
+#define NOMASTER       0               /* no good master */
+#define SLAVE          1
+#define MASTER         2
+#define IGNORE         4
+#define ALL            (SLAVE|MASTER|IGNORE)
+#define SUBMASTER      (SLAVE|MASTER)
+
+#define NHOSTS         1013            /* max of hosts controlled by timed
+                                        * This must be a prime number.
+                                        */
+struct hosttbl {
+       struct  hosttbl *h_bak;         /* hash chain */
+       struct  hosttbl *h_fwd;
+       struct  hosttbl *l_bak;         /* "sequential" list */
+       struct  hosttbl *l_fwd;
+       struct  netinfo *ntp;
+       struct  sockaddr_in addr;
+       char    name[MAXHOSTNAMELEN+1];
+       u_char  head;                   /* 1=head of hash chain */
+       u_char  good;                   /* 0=trusted host, for averaging */
+       u_char  noanswer;               /* count of failures to answer */
+       u_char  need_set;               /* need a SETTIME */
+       u_short seq;
+       long    delta;
+};
+
+/* closed hash table with internal chaining */
+extern struct hosttbl hosttbl[NHOSTS+1];
+#define self hosttbl[0]
+#define hostname (self.name)
+
+
+struct netinfo {
+       struct  netinfo *next;
+       struct  in_addr net;
+       u_long  mask;
+       struct  in_addr my_addr;
+       struct  sockaddr_in dest_addr;  /* broadcast addr or point-point */
+       long    status;
+       struct timeval slvwait;         /* delay before sending our time */
+       int     quit_count;             /* recent QUITs */
+};
+
+#include "extern.h"
+
+#define tvtomsround(tv) ((tv).tv_sec*1000 + ((tv).tv_usec + 500)/1000)
+
+extern struct netinfo *nettab;
+extern int status;
+extern int trace;
+extern int sock;
+extern struct sockaddr_in from;
+extern struct timeval from_when;       /* when the last msg arrived */
+extern u_short sequence;               /* TSP message sequence number */
+extern struct netinfo *fromnet, *slavenet;
+extern FILE *fd;
+extern long delay1, delay2;
+extern int nslavenets;                 /* nets were I could be a slave */
+extern int nmasternets;                        /* nets were I could be a master */
+extern int nignorednets;               /* ignored nets */
+extern int nnets;                      /* nets I am connected to */
+
+
+#define trace_msg(msg)         {if (trace) fprintf(fd, msg);}
+
+#define trace_sendto_err(addr) {                                       \
+       int st_errno = errno;                                           \
+       syslog(LOG_ERR, "%s %d: sendto %s: %m",                         \
+               __FILE__, __LINE__, inet_ntoa(addr));                   \
+       if (trace)                                                      \
+               fprintf(fd, "%s %d: sendto %s: %d", __FILE__, __LINE__, \
+                       inet_ntoa(addr), st_errno);                     \
+}
+
+
+# define max(a,b)      (a<b ? b : a)
+# define min(a,b)      (a>b ? b : a)
+# define abs(x)                (x>=0 ? x : -(x))
diff --git a/timed.tproj/timed.tproj/master.c b/timed.tproj/timed.tproj/master.c
new file mode 100644 (file)
index 0000000..ddd3215
--- /dev/null
@@ -0,0 +1,930 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)master.c   8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#include <setjmp.h>
+#ifdef sgi
+#include <sys/schedctl.h>
+#endif /* sgi */
+#include <utmp.h>
+#include "pathnames.h"
+
+extern int measure_delta;
+extern jmp_buf jmpenv;
+extern int Mflag;
+extern int justquit;
+
+static int dictate;
+static int slvcount;                   /* slaves listening to our clock */
+
+static void mchgdate __P((struct tsp *));
+
+#ifdef sgi
+extern void logwtmp __P((struct timeval *, struct timeval *));
+#else
+extern void logwtmp __P((char *, char *, char *));
+#endif /* sgi */
+
+/*
+ * The main function of `master' is to periodically compute the differences
+ * (deltas) between its clock and the clocks of the slaves, to compute the
+ * network average delta, and to send to the slaves the differences between
+ * their individual deltas and the network delta.
+ * While waiting, it receives messages from the slaves (i.e. requests for
+ * master's name, remote requests to set the network time, ...), and
+ * takes the appropriate action.
+ */
+int
+master()
+{
+       struct hosttbl *htp;
+       long pollingtime;
+#define POLLRATE 4
+       int polls;
+       struct timeval wait, ntime;
+       struct tsp *msg, *answer, to;
+       char newdate[32];
+       struct sockaddr_in taddr;
+       char tname[MAXHOSTNAMELEN];
+       struct netinfo *ntp;
+       int i;
+
+       syslog(LOG_NOTICE, "This machine is master");
+       if (trace)
+               fprintf(fd, "This machine is master\n");
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+               if (ntp->status == MASTER)
+                       masterup(ntp);
+       }
+       (void)gettimeofday(&ntime, 0);
+       pollingtime = ntime.tv_sec+3;
+       if (justquit)
+               polls = 0;
+       else
+               polls = POLLRATE-1;
+
+/* Process all outstanding messages before spending the long time necessary
+ *     to update all timers.
+ */
+loop:
+       (void)gettimeofday(&ntime, 0);
+       wait.tv_sec = pollingtime - ntime.tv_sec;
+       if (wait.tv_sec < 0)
+               wait.tv_sec = 0;
+       wait.tv_usec = 0;
+       msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
+       if (!msg) {
+               (void)gettimeofday(&ntime, 0);
+               if (ntime.tv_sec >= pollingtime) {
+                       pollingtime = ntime.tv_sec + SAMPLEINTVL;
+                       get_goodgroup(0);
+
+/* If a bogus master told us to quit, we can have decided to ignore a
+ * network.  Therefore, periodically try to take over everything.
+ */
+                       polls = (polls + 1) % POLLRATE;
+                       if (0 == polls && nignorednets > 0) {
+                               trace_msg("Looking for nets to re-master\n");
+                               for (ntp = nettab; ntp; ntp = ntp->next) {
+                                       if (ntp->status == IGNORE
+                                           || ntp->status == NOMASTER) {
+                                               lookformaster(ntp);
+                                               if (ntp->status == MASTER) {
+                                                       masterup(ntp);
+                                                       polls = POLLRATE-1;
+                                               }
+                                       }
+                                       if (ntp->status == MASTER
+                                           && --ntp->quit_count < 0)
+                                               ntp->quit_count = 0;
+                               }
+                               if (polls != 0)
+                                       setstatus();
+                       }
+
+                       synch(0L);
+
+                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                               to.tsp_type = TSP_LOOP;
+                               to.tsp_vers = TSPVERSION;
+                               to.tsp_seq = sequence++;
+                               to.tsp_hopcnt = MAX_HOPCNT;
+                               (void)strcpy(to.tsp_name, hostname);
+                               bytenetorder(&to);
+                               if (sendto(sock, (char *)&to,
+                                          sizeof(struct tsp), 0,
+                                          (struct sockaddr*)&ntp->dest_addr,
+                                          sizeof(ntp->dest_addr)) < 0) {
+                                  trace_sendto_err(ntp->dest_addr.sin_addr);
+                               }
+                       }
+               }
+
+
+       } else {
+               switch (msg->tsp_type) {
+
+               case TSP_MASTERREQ:
+                       break;
+
+               case TSP_SLAVEUP:
+                       newslave(msg);
+                       break;
+
+               case TSP_SETDATE:
+                       /*
+                        * XXX check to see it is from ourself
+                        */
+#ifdef sgi
+                       (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+                       (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+                       if (!good_host_name(msg->tsp_name)) {
+                               syslog(LOG_NOTICE,
+                                      "attempted date change by %s to %s",
+                                      msg->tsp_name, newdate);
+                               spreadtime();
+                               break;
+                       }
+
+                       mchgdate(msg);
+                       (void)gettimeofday(&ntime, 0);
+                       pollingtime = ntime.tv_sec + SAMPLEINTVL;
+                       break;
+
+               case TSP_SETDATEREQ:
+                       if (!fromnet || fromnet->status != MASTER)
+                               break;
+#ifdef sgi
+                       (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+                       (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+                       htp = findhost(msg->tsp_name);
+                       if (htp == 0) {
+                               syslog(LOG_ERR,
+                                      "attempted SET DATEREQ by uncontrolled %s to %s",
+                                      msg->tsp_name, newdate);
+                               break;
+                       }
+                       if (htp->seq == msg->tsp_seq)
+                               break;
+                       htp->seq = msg->tsp_seq;
+                       if (!htp->good) {
+                               syslog(LOG_NOTICE,
+                               "attempted SET DATEREQ by untrusted %s to %s",
+                                      msg->tsp_name, newdate);
+                               spreadtime();
+                               break;
+                       }
+
+                       mchgdate(msg);
+                       (void)gettimeofday(&ntime, 0);
+                       pollingtime = ntime.tv_sec + SAMPLEINTVL;
+                       break;
+
+               case TSP_MSITE:
+                       xmit(TSP_ACK, msg->tsp_seq, &from);
+                       break;
+
+               case TSP_MSITEREQ:
+                       break;
+
+               case TSP_TRACEON:
+                       traceon();
+                       break;
+
+               case TSP_TRACEOFF:
+                       traceoff("Tracing ended at %s\n");
+                       break;
+
+               case TSP_ELECTION:
+                       if (!fromnet)
+                               break;
+                       if (fromnet->status == MASTER) {
+                               pollingtime = 0;
+                               (void)addmach(msg->tsp_name, &from,fromnet);
+                       }
+                       taddr = from;
+                       (void)strcpy(tname, msg->tsp_name);
+                       to.tsp_type = TSP_QUIT;
+                       (void)strcpy(to.tsp_name, hostname);
+                       answer = acksend(&to, &taddr, tname,
+                                        TSP_ACK, 0, 1);
+                       if (answer == NULL) {
+                               syslog(LOG_ERR, "election error by %s",
+                                      tname);
+                       }
+                       break;
+
+               case TSP_CONFLICT:
+                       /*
+                        * After a network partition, there can be
+                        * more than one master: the first slave to
+                        * come up will notify here the situation.
+                        */
+                       if (!fromnet || fromnet->status != MASTER)
+                               break;
+                       (void)strcpy(to.tsp_name, hostname);
+
+                       /* The other master often gets into the same state,
+                        * with boring results if we stay at it forever.
+                        */
+                       ntp = fromnet;  /* (acksend() can leave fromnet=0 */
+                       for (i = 0; i < 3; i++) {
+                               to.tsp_type = TSP_RESOLVE;
+                               (void)strcpy(to.tsp_name, hostname);
+                               answer = acksend(&to, &ntp->dest_addr,
+                                                ANYADDR, TSP_MASTERACK,
+                                                ntp, 0);
+                               if (!answer)
+                                       break;
+                               htp = addmach(answer->tsp_name,&from,ntp);
+                               to.tsp_type = TSP_QUIT;
+                               msg = acksend(&to, &htp->addr, htp->name,
+                                             TSP_ACK, 0, htp->noanswer);
+                               if (msg == NULL) {
+                                       syslog(LOG_ERR,
+                                   "no response from %s to CONFLICT-QUIT",
+                                              htp->name);
+                               }
+                       }
+                       masterup(ntp);
+                       pollingtime = 0;
+                       break;
+
+               case TSP_RESOLVE:
+                       if (!fromnet || fromnet->status != MASTER)
+                               break;
+                       /*
+                        * do not want to call synch() while waiting
+                        * to be killed!
+                        */
+                       (void)gettimeofday(&ntime, (struct timezone *)0);
+                       pollingtime = ntime.tv_sec + SAMPLEINTVL;
+                       break;
+
+               case TSP_QUIT:
+                       doquit(msg);            /* become a slave */
+                       break;
+
+               case TSP_LOOP:
+                       if (!fromnet || fromnet->status != MASTER
+                           || !strcmp(msg->tsp_name, hostname))
+                               break;
+                       /*
+                        * We should not have received this from a net
+                        * we are master on.  There must be two masters.
+                        */
+                       htp = addmach(msg->tsp_name, &from,fromnet);
+                       to.tsp_type = TSP_QUIT;
+                       (void)strcpy(to.tsp_name, hostname);
+                       answer = acksend(&to, &htp->addr, htp->name,
+                                        TSP_ACK, 0, 1);
+                       if (!answer) {
+                               syslog(LOG_WARNING,
+                               "loop breakage: no reply from %s=%s to QUIT",
+                                   htp->name, inet_ntoa(htp->addr.sin_addr));
+                               (void)remmach(htp);
+                       }
+
+               case TSP_TEST:
+                       if (trace) {
+                               fprintf(fd,
+               "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n",
+               nnets, nmasternets, nslavenets, nignorednets);
+                               setstatus();
+                       }
+                       pollingtime = 0;
+                       polls = POLLRATE-1;
+                       break;
+
+               default:
+                       if (trace) {
+                               fprintf(fd, "garbage message: ");
+                               print(msg, &from);
+                       }
+                       break;
+               }
+       }
+       goto loop;
+}
+
+
+/*
+ * change the system date on the master
+ */
+static void
+mchgdate(msg)
+       struct tsp *msg;
+{
+       char tname[MAXHOSTNAMELEN];
+       char olddate[32];
+       struct timeval otime, ntime;
+
+       (void)strcpy(tname, msg->tsp_name);
+
+       xmit(TSP_DATEACK, msg->tsp_seq, &from);
+
+       (void)strcpy(olddate, date());
+
+       /* adjust time for residence on the queue */
+       (void)gettimeofday(&otime, 0);
+       adj_msg_time(msg,&otime);
+
+       timevalsub(&ntime, &msg->tsp_time, &otime);
+       if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
+               /*
+                * do not change the clock if we can adjust it
+                */
+               dictate = 3;
+               synch(tvtomsround(ntime));
+       } else {
+#ifdef sgi
+               if (0 > settimeofday(&msg->tsp_time, 0)) {
+                       syslog(LOG_ERR, "settimeofday(): %m");
+               }
+               logwtmp(&otime, &msg->tsp_time);
+#else
+               logwtmp("|", "date", "");
+               (void)settimeofday(&msg->tsp_time, 0);
+               logwtmp("}", "date", "");
+#endif /* sgi */
+               spreadtime();
+       }
+
+       syslog(LOG_NOTICE, "date changed by %s from %s",
+              tname, olddate);
+}
+
+
+/*
+ * synchronize all of the slaves
+ */
+void
+synch(mydelta)
+       long mydelta;
+{
+       struct hosttbl *htp;
+       int measure_status;
+       struct timeval check, stop, wait;
+#ifdef sgi
+       int pri;
+#endif /* sgi */
+
+       if (slvcount > 0) {
+               if (trace)
+                       fprintf(fd, "measurements starting at %s\n", date());
+               (void)gettimeofday(&check, 0);
+#ifdef sgi
+               /* run fast to get good time */
+               pri = schedctl(NDPRI,0,NDPHIMIN);
+               if (pri < 0)
+                       syslog(LOG_ERR, "schedctl(): %m");
+#endif /* sgi */
+               for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+                       if (htp->noanswer != 0) {
+                               measure_status = measure(500, 100,
+                                                        htp->name,
+                                                        &htp->addr,0);
+                       } else {
+                               measure_status = measure(3000, 100,
+                                                        htp->name,
+                                                        &htp->addr,0);
+                       }
+                       if (measure_status != GOOD) {
+                               /* The slave did not respond.  We have
+                                * just wasted lots of time on it.
+                                */
+                               htp->delta = HOSTDOWN;
+                               if (++htp->noanswer >= LOSTHOST) {
+                                       if (trace) {
+                                               fprintf(fd,
+                                       "purging %s for not answering ICMP\n",
+                                                       htp->name);
+                                               (void)fflush(fd);
+                                       }
+                                       htp = remmach(htp);
+                               }
+                       } else {
+                               htp->delta = measure_delta;
+                       }
+                       (void)gettimeofday(&stop, 0);
+                       timevalsub(&stop, &stop, &check);
+                       if (stop.tv_sec >= 1) {
+                               if (trace)
+                                       (void)fflush(fd);
+                               /*
+                                * ack messages periodically
+                                */
+                               wait.tv_sec = 0;
+                               wait.tv_usec = 0;
+                               if (0 != readmsg(TSP_TRACEON,ANYADDR,
+                                                &wait,0))
+                                       traceon();
+                               (void)gettimeofday(&check, 0);
+                       }
+               }
+#ifdef sgi
+               if (pri >= 0)
+                       (void)schedctl(NDPRI,0,pri);
+#endif /* sgi */
+               if (trace)
+                       fprintf(fd, "measurements finished at %s\n", date());
+       }
+       if (!(status & SLAVE)) {
+               if (!dictate) {
+                       mydelta = networkdelta();
+               } else {
+                       dictate--;
+               }
+       }
+       if (trace && (mydelta != 0 || (status & SLAVE)))
+               fprintf(fd,"local correction of %ld ms.\n", mydelta);
+       correct(mydelta);
+}
+
+/*
+ * sends the time to each slave after the master
+ * has received the command to set the network time
+ */
+void
+spreadtime()
+{
+       struct hosttbl *htp;
+       struct tsp to;
+       struct tsp *answer;
+
+/* Do not listen to the consensus after forcing the time.  This is because
+ *     the consensus takes a while to reach the time we are dictating.
+ */
+       dictate = 2;
+       for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+               to.tsp_type = TSP_SETTIME;
+               (void)strcpy(to.tsp_name, hostname);
+               (void)gettimeofday(&to.tsp_time, 0);
+               answer = acksend(&to, &htp->addr, htp->name,
+                                TSP_ACK, 0, htp->noanswer);
+               if (answer == 0) {
+                       /* We client does not respond, then we have
+                        * just wasted lots of time on it.
+                        */
+                       syslog(LOG_WARNING,
+                              "no reply to SETTIME from %s", htp->name);
+                       if (++htp->noanswer >= LOSTHOST) {
+                               if (trace) {
+                                       fprintf(fd,
+                                            "purging %s for not answering",
+                                               htp->name);
+                                       (void)fflush(fd);
+                               }
+                               htp = remmach(htp);
+                       }
+               }
+       }
+}
+
+void
+prthp(delta)
+       clock_t delta;
+{
+       static time_t next_time;
+       time_t this_time;
+       struct tms tm;
+       struct hosttbl *htp;
+       int length, l;
+       int i;
+
+       if (!fd)                        /* quit if tracing already off */
+               return;
+
+       this_time = times(&tm);
+       if (this_time + delta < next_time)
+               return;
+       next_time = this_time + CLK_TCK;
+
+       fprintf(fd, "host table: %d entries at %s\n", slvcount, date());
+       htp = self.l_fwd;
+       length = 1;
+       for (i = 1; i <= slvcount; i++, htp = htp->l_fwd) {
+               l = strlen(htp->name) + 1;
+               if (length+l >= 80) {
+                       fprintf(fd, "\n");
+                       length = 0;
+               }
+               length += l;
+               fprintf(fd, " %s", htp->name);
+       }
+       fprintf(fd, "\n");
+}
+
+
+static struct hosttbl *newhost_hash;
+static struct hosttbl *lasthfree = &hosttbl[0];
+
+
+struct hosttbl *                       /* answer or 0 */
+findhost(name)
+       char *name;
+{
+       int i, j;
+       struct hosttbl *htp;
+       char *p;
+
+       j= 0;
+       for (p = name, i = 0; i < 8 && *p != '\0'; i++, p++)
+               j = (j << 2) ^ *p;
+       newhost_hash = &hosttbl[j % NHOSTS];
+
+       htp = newhost_hash;
+       if (htp->name[0] == '\0')
+               return(0);
+       do {
+               if (!strcmp(name, htp->name))
+                       return(htp);
+               htp = htp->h_fwd;
+       } while (htp != newhost_hash);
+       return(0);
+}
+
+/*
+ * add a host to the list of controlled machines if not already there
+ */
+struct hosttbl *
+addmach(name, addr, ntp)
+       char *name;
+       struct sockaddr_in *addr;
+       struct netinfo *ntp;
+{
+       struct hosttbl *ret, *p, *b, *f;
+
+       ret = findhost(name);
+       if (ret == 0) {
+               if (slvcount >= NHOSTS) {
+                       if (trace) {
+                               fprintf(fd, "no more slots in host table\n");
+                               prthp(CLK_TCK);
+                       }
+                       syslog(LOG_ERR, "no more slots in host table");
+                       Mflag = 0;
+                       longjmp(jmpenv, 2); /* give up and be a slave */
+               }
+
+               /* if our home hash slot is occupied, find a free entry
+                * in the hash table
+                */
+               if (newhost_hash->name[0] != '\0') {
+                       do {
+                               ret = lasthfree;
+                               if (++lasthfree > &hosttbl[NHOSTS])
+                                       lasthfree = &hosttbl[1];
+                       } while (ret->name[0] != '\0');
+
+                       if (!newhost_hash->head) {
+                               /* Move an interloper using our home.  Use
+                                * scratch pointers in case the new head is
+                                * pointing to itself.
+                                */
+                               f = newhost_hash->h_fwd;
+                               b = newhost_hash->h_bak;
+                               f->h_bak = ret;
+                               b->h_fwd = ret;
+                               f = newhost_hash->l_fwd;
+                               b = newhost_hash->l_bak;
+                               f->l_bak = ret;
+                               b->l_fwd = ret;
+                               bcopy(newhost_hash,ret,sizeof(*ret));
+                               ret = newhost_hash;
+                               ret->head = 1;
+                               ret->h_fwd = ret;
+                               ret->h_bak = ret;
+                       } else {
+                               /* link to an existing chain in our home
+                                */
+                               ret->head = 0;
+                               p = newhost_hash->h_bak;
+                               ret->h_fwd = newhost_hash;
+                               ret->h_bak = p;
+                               p->h_fwd = ret;
+                               newhost_hash->h_bak = ret;
+                       }
+               } else {
+                       ret = newhost_hash;
+                       ret->head = 1;
+                       ret->h_fwd = ret;
+                       ret->h_bak = ret;
+               }
+               ret->addr = *addr;
+               ret->ntp = ntp;
+               (void)strncpy(ret->name, name, sizeof(ret->name));
+               ret->good = good_host_name(name);
+               ret->l_fwd = &self;
+               ret->l_bak = self.l_bak;
+               self.l_bak->l_fwd = ret;
+               self.l_bak = ret;
+               slvcount++;
+
+               ret->noanswer = 0;
+               ret->need_set = 1;
+
+       } else {
+               ret->noanswer = (ret->noanswer != 0);
+       }
+
+       /* need to clear sequence number anyhow */
+       ret->seq = 0;
+       return(ret);
+}
+
+/*
+ * remove the machine with the given index in the host table.
+ */
+struct hosttbl *
+remmach(htp)
+       struct hosttbl *htp;
+{
+       struct hosttbl *lprv, *hnxt, *f, *b;
+
+       if (trace)
+               fprintf(fd, "remove %s\n", htp->name);
+
+       /* get out of the lists */
+       htp->l_fwd->l_bak = lprv = htp->l_bak;
+       htp->l_bak->l_fwd = htp->l_fwd;
+       htp->h_fwd->h_bak = htp->h_bak;
+       htp->h_bak->h_fwd = hnxt = htp->h_fwd;
+
+       /* If we are in the home slot, pull up the chain */
+       if (htp->head && hnxt != htp) {
+               if (lprv == hnxt)
+                       lprv = htp;
+
+               /* Use scratch pointers in case the new head is pointing to
+                * itself.
+                */
+               f = hnxt->h_fwd;
+               b = hnxt->h_bak;
+               f->h_bak = htp;
+               b->h_fwd = htp;
+               f = hnxt->l_fwd;
+               b = hnxt->l_bak;
+               f->l_bak = htp;
+               b->l_fwd = htp;
+               hnxt->head = 1;
+               bcopy(hnxt, htp, sizeof(*htp));
+               lasthfree = hnxt;
+       } else {
+               lasthfree = htp;
+       }
+
+       lasthfree->name[0] = '\0';
+       lasthfree->h_fwd = 0;
+       lasthfree->l_fwd = 0;
+       slvcount--;
+
+       return lprv;
+}
+
+
+/*
+ * Remove all the machines from the host table that exist on the given
+ * network.  This is called when a master transitions to a slave on a
+ * given network.
+ */
+void
+rmnetmachs(ntp)
+       struct netinfo *ntp;
+{
+       struct hosttbl *htp;
+
+       if (trace)
+               prthp(CLK_TCK);
+       for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+               if (ntp == htp->ntp)
+                       htp = remmach(htp);
+       }
+       if (trace)
+               prthp(CLK_TCK);
+}
+
+void
+masterup(net)
+       struct netinfo *net;
+{
+       xmit(TSP_MASTERUP, 0, &net->dest_addr);
+
+       /*
+        * Do not tell new slaves our time for a while.  This ensures
+        * we do not tell them to start using our time, before we have
+        * found a good master.
+        */
+       (void)gettimeofday(&net->slvwait, 0);
+}
+
+void
+newslave(msg)
+       struct tsp *msg;
+{
+       struct hosttbl *htp;
+       struct tsp *answer, to;
+       struct timeval now;
+
+       if (!fromnet || fromnet->status != MASTER)
+               return;
+
+       htp = addmach(msg->tsp_name, &from,fromnet);
+       htp->seq = msg->tsp_seq;
+       if (trace)
+               prthp(0);
+
+       /*
+        * If we are stable, send our time to the slave.
+        * Do not go crazy if the date has been changed.
+        */
+       (void)gettimeofday(&now, 0);
+       if (now.tv_sec >= fromnet->slvwait.tv_sec+3
+           || now.tv_sec < fromnet->slvwait.tv_sec) {
+               to.tsp_type = TSP_SETTIME;
+               (void)strcpy(to.tsp_name, hostname);
+               (void)gettimeofday(&to.tsp_time, 0);
+               answer = acksend(&to, &htp->addr,
+                                htp->name, TSP_ACK,
+                                0, htp->noanswer);
+               if (answer) {
+                       htp->need_set = 0;
+               } else {
+                       syslog(LOG_WARNING,
+                              "no reply to initial SETTIME from %s",
+                              htp->name);
+                       htp->noanswer = LOSTHOST;
+               }
+       }
+}
+
+
+/*
+ * react to a TSP_QUIT:
+ */
+void
+doquit(msg)
+       struct tsp *msg;
+{
+       if (fromnet->status == MASTER) {
+               if (!good_host_name(msg->tsp_name)) {
+                       if (fromnet->quit_count <= 0) {
+                               syslog(LOG_NOTICE,"untrusted %s told us QUIT",
+                                      msg->tsp_name);
+                               suppress(&from, msg->tsp_name, fromnet);
+                               fromnet->quit_count = 1;
+                               return;
+                       }
+                       syslog(LOG_NOTICE, "untrusted %s told us QUIT twice",
+                              msg->tsp_name);
+                       fromnet->quit_count = 2;
+                       fromnet->status = NOMASTER;
+               } else {
+                       fromnet->status = SLAVE;
+               }
+               rmnetmachs(fromnet);
+               longjmp(jmpenv, 2);             /* give up and be a slave */
+
+       } else {
+               if (!good_host_name(msg->tsp_name)) {
+                       syslog(LOG_NOTICE, "untrusted %s told us QUIT",
+                              msg->tsp_name);
+                       fromnet->quit_count = 2;
+               }
+       }
+}
+
+void
+traceon()
+{
+       if (!fd) {
+               fd = fopen(_PATH_TIMEDLOG, "w");
+               if (!fd) {
+                       trace = 0;
+                       return;
+               }
+               fprintf(fd,"Tracing started at %s\n", date());
+       }
+       trace = 1;
+       get_goodgroup(1);
+       setstatus();
+       prthp(CLK_TCK);
+}
+
+
+void
+traceoff(msg)
+       char *msg;
+{
+       get_goodgroup(1);
+       setstatus();
+       prthp(CLK_TCK);
+       if (trace) {
+               fprintf(fd, msg, date());
+               (void)fclose(fd);
+               fd = 0;
+       }
+#ifdef GPROF
+       moncontrol(0);
+       _mcleanup();
+       moncontrol(1);
+#endif
+       trace = OFF;
+}
+
+
+#ifdef sgi
+void
+logwtmp(otime, ntime)
+       struct timeval *otime, *ntime;
+{
+       static struct utmp wtmp[2] = {
+               {"","",OTIME_MSG,0,OLD_TIME,0,0,0},
+               {"","",NTIME_MSG,0,NEW_TIME,0,0,0}
+       };
+       static char *wtmpfile = WTMP_FILE;
+       int f;
+
+       wtmp[0].ut_time = otime->tv_sec + (otime->tv_usec + 500000) / 1000000;
+       wtmp[1].ut_time = ntime->tv_sec + (ntime->tv_usec + 500000) / 1000000;
+       if (wtmp[0].ut_time == wtmp[1].ut_time)
+               return;
+
+       setutent();
+       (void)pututline(&wtmp[0]);
+       (void)pututline(&wtmp[1]);
+       endutent();
+       if ((f = open(wtmpfile, O_WRONLY|O_APPEND)) >= 0) {
+               (void) write(f, (char *)wtmp, sizeof(wtmp));
+               (void) close(f);
+       }
+}
+#endif /* sgi */
diff --git a/timed.tproj/timed.tproj/measure.c b/timed.tproj/timed.tproj/measure.c
new file mode 100644 (file)
index 0000000..6b809b2
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)measure.c  8.2 (Berkeley) 3/26/95";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#define MSEC_DAY       (SECDAY*1000)
+
+#define PACKET_IN      1024
+
+#define MSGS           5               /* timestamps to average */
+#define TRIALS         10              /* max # of timestamps sent */
+
+extern int sock_raw;
+
+int measure_delta;
+
+static n_short seqno = 0;
+
+/*
+ * Measures the differences between machines' clocks using
+ * ICMP timestamp messages.
+ */
+int                                    /* status val defined in globals.h */
+measure(maxmsec, wmsec, hname, addr, print)
+       u_long maxmsec;                 /* wait this many msec at most */
+       u_long wmsec;                   /* msec to wait for an answer */
+       char *hname;
+       struct sockaddr_in *addr;
+       int print;                      /* print complaints on stderr */
+{
+       int length;
+       int measure_status;
+       int rcvcount, trials;
+       int cc, count;
+       fd_set ready;
+       long sendtime, recvtime, histime1, histime2;
+       long idelta, odelta, total;
+       long min_idelta, min_odelta;
+       struct timeval tdone, tcur, ttrans, twait, tout;
+       u_char packet[PACKET_IN], opacket[64];
+       register struct icmp *icp = (struct icmp *) packet;
+       register struct icmp *oicp = (struct icmp *) opacket;
+       struct ip *ip = (struct ip *) packet;
+
+       min_idelta = min_odelta = 0x7fffffff;
+       measure_status = HOSTDOWN;
+       measure_delta = HOSTDOWN;
+       errno = 0;
+
+       /* open raw socket used to measure time differences */
+       if (sock_raw < 0) {
+               sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+               if (sock_raw < 0)  {
+                       syslog(LOG_ERR, "opening raw socket: %m");
+                       goto quit;
+               }
+       }
+           
+
+       /*
+        * empty the icmp input queue
+        */
+       FD_ZERO(&ready);
+       for (;;) {
+               tout.tv_sec = tout.tv_usec = 0;
+               FD_SET(sock_raw, &ready);
+               if (select(sock_raw+1, &ready, 0,0, &tout)) {
+                       length = sizeof(struct sockaddr_in);
+                       cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
+                                     0,&length);
+                       if (cc < 0)
+                               goto quit;
+                       continue;
+               }
+               break;
+       }
+
+       /*
+        * Choose the smallest transmission time in each of the two
+        * directions. Use these two latter quantities to compute the delta
+        * between the two clocks.
+        */
+
+       oicp->icmp_type = ICMP_TSTAMP;
+       oicp->icmp_code = 0;
+       oicp->icmp_id = getpid();
+       oicp->icmp_rtime = 0;
+       oicp->icmp_ttime = 0;
+       oicp->icmp_seq = seqno;
+
+       FD_ZERO(&ready);
+
+#ifdef sgi
+       sginap(1);                      /* start at a clock tick */
+#endif /* sgi */
+
+       (void)gettimeofday(&tdone, 0);
+       mstotvround(&tout, maxmsec);
+       timevaladd(&tdone, &tout);              /* when we give up */
+
+       mstotvround(&twait, wmsec);
+
+       rcvcount = 0;
+       trials = 0;
+       while (rcvcount < MSGS) {
+               (void)gettimeofday(&tcur, 0);
+
+               /*
+                * keep sending until we have sent the max
+                */
+               if (trials < TRIALS) {
+                       trials++;
+                       oicp->icmp_otime = htonl((tcur.tv_sec % SECDAY) * 1000
+                                                + tcur.tv_usec / 1000);
+                       oicp->icmp_cksum = 0;
+                       oicp->icmp_cksum = in_cksum((u_short*)oicp,
+                                                   sizeof(*oicp));
+
+                       count = sendto(sock_raw, opacket, sizeof(*oicp), 0,
+                                      (struct sockaddr*)addr,
+                                      sizeof(struct sockaddr));
+                       if (count < 0) {
+                               if (measure_status == HOSTDOWN)
+                                       measure_status = UNREACHABLE;
+                               goto quit;
+                       }
+                       ++oicp->icmp_seq;
+
+                       ttrans = tcur;
+                       timevaladd(&ttrans, &twait);
+               } else {
+                       ttrans = tdone;
+               }
+
+               while (rcvcount < trials) {
+                       timevalsub(&tout, &ttrans, &tcur);
+                       if (tout.tv_sec < 0)
+                               tout.tv_sec = 0;
+
+                       FD_SET(sock_raw, &ready);
+                       count = select(sock_raw+1, &ready, (fd_set *)0,
+                                      (fd_set *)0, &tout);
+                       (void)gettimeofday(&tcur, (struct timezone *)0);
+                       if (count <= 0)
+                               break;
+
+                       length = sizeof(struct sockaddr_in);
+                       cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
+                                     0,&length);
+                       if (cc < 0)
+                               goto quit;
+
+                       /* 
+                        * got something.  See if it is ours
+                        */
+                       icp = (struct icmp *)(packet + (ip->ip_hl << 2));
+                       if (cc < sizeof(*ip)
+                           || icp->icmp_type != ICMP_TSTAMPREPLY
+                           || icp->icmp_id != oicp->icmp_id
+                           || icp->icmp_seq < seqno
+                           || icp->icmp_seq >= oicp->icmp_seq)
+                               continue;
+
+
+                       sendtime = ntohl(icp->icmp_otime);
+                       recvtime = ((tcur.tv_sec % SECDAY) * 1000 +
+                                   tcur.tv_usec / 1000);
+
+                       total = recvtime-sendtime;
+                       if (total < 0)  /* do not hassle midnight */
+                               continue;
+
+                       rcvcount++;
+                       histime1 = ntohl(icp->icmp_rtime);
+                       histime2 = ntohl(icp->icmp_ttime);
+                       /*
+                        * a host using a time format different from
+                        * msec. since midnight UT (as per RFC792) should
+                        * set the high order bit of the 32-bit time
+                        * value it transmits.
+                        */
+                       if ((histime1 & 0x80000000) != 0) {
+                               measure_status = NONSTDTIME;
+                               goto quit;
+                       }
+                       measure_status = GOOD;
+
+                       idelta = recvtime-histime2;
+                       odelta = histime1-sendtime;
+
+                       /* do not be confused by midnight */
+                       if (idelta < -MSEC_DAY/2) idelta += MSEC_DAY;
+                       else if (idelta > MSEC_DAY/2) idelta -= MSEC_DAY;
+
+                       if (odelta < -MSEC_DAY/2) odelta += MSEC_DAY;
+                       else if (odelta > MSEC_DAY/2) odelta -= MSEC_DAY;
+
+                       /* save the quantization error so that we can get a
+                        * measurement finer than our system clock.
+                        */
+                       if (total < MIN_ROUND) {
+                               measure_delta = (odelta - idelta)/2;
+                               goto quit;
+                       }
+
+                       if (idelta < min_idelta)
+                               min_idelta = idelta;
+                       if (odelta < min_odelta)
+                               min_odelta = odelta;
+
+                       measure_delta = (min_odelta - min_idelta)/2;
+               }
+
+               if (tcur.tv_sec > tdone.tv_sec
+                   || (tcur.tv_sec == tdone.tv_sec
+                       && tcur.tv_usec >= tdone.tv_usec))
+                       break;
+       }
+
+quit:
+       seqno += TRIALS;                /* allocate our sequence numbers */
+
+       /*
+        * If no answer is received for TRIALS consecutive times,
+        * the machine is assumed to be down
+        */
+       if (measure_status == GOOD) {
+               if (trace) {
+                       fprintf(fd,
+                               "measured delta %4d, %d trials to %-15s %s\n",
+                               measure_delta, trials,
+                               inet_ntoa(addr->sin_addr), hname);
+               }
+       } else if (print) {
+               if (errno != 0)
+                       fprintf(stderr, "measure %s: %s\n", hname,
+                               strerror(errno));
+       } else {
+               if (errno != 0) {
+                       syslog(LOG_ERR, "measure %s: %m", hname);
+               } else {
+                       syslog(LOG_ERR, "measure: %s did not respond", hname);
+               }
+               if (trace) {
+                       fprintf(fd,
+                               "measure: %s failed after %d trials\n",
+                               hname, trials);
+                       (void)fflush(fd);
+               }
+       }
+
+       return(measure_status);
+}
+
+
+
+
+
+/*
+ * round a number of milliseconds into a struct timeval
+ */
+void
+mstotvround(res, x)
+       struct timeval *res;
+       long x;
+{
+#ifndef sgi
+       if (x < 0)
+               x = -((-x + 3)/5);
+       else
+               x = (x+3)/5;
+       x *= 5;
+#endif /* sgi */
+       res->tv_sec = x/1000;
+       res->tv_usec = (x-res->tv_sec*1000)*1000;
+       if (res->tv_usec < 0) {
+               res->tv_usec += 1000000;
+               res->tv_sec--;
+       }
+}
+
+void
+timevaladd(tv1, tv2)
+       struct timeval *tv1, *tv2;
+{
+       tv1->tv_sec += tv2->tv_sec;
+       tv1->tv_usec += tv2->tv_usec;
+       if (tv1->tv_usec >= 1000000) {
+               tv1->tv_sec++;
+               tv1->tv_usec -= 1000000;
+       }
+       if (tv1->tv_usec < 0) {
+               tv1->tv_sec--;
+               tv1->tv_usec += 1000000;
+       }
+}
+
+void
+timevalsub(res, tv1, tv2)
+       struct timeval *res, *tv1, *tv2;
+{
+       res->tv_sec = tv1->tv_sec - tv2->tv_sec;
+       res->tv_usec = tv1->tv_usec - tv2->tv_usec;
+       if (res->tv_usec >= 1000000) {
+               res->tv_sec++;
+               res->tv_usec -= 1000000;
+       }
+       if (res->tv_usec < 0) {
+               res->tv_sec--;
+               res->tv_usec += 1000000;
+       }
+}
diff --git a/timed.tproj/timed.tproj/networkdelta.c b/timed.tproj/timed.tproj/networkdelta.c
new file mode 100644 (file)
index 0000000..51576f6
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)networkdelta.c     8.3 (Berkeley) 4/27/95";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+
+static long median __P((double, float *, long *, long *, unsigned int));
+
+/*
+ * Compute a corrected date.
+ *     Compute the median of the reasonable differences.  First compute
+ *     the median of all authorized differences, and then compute the
+ *     median of all differences that are reasonably close to the first
+ *     median.
+ *
+ * This differs from the original BSD implementation, which looked for
+ *     the largest group of machines with essentially the same date.
+ *     That assumed that machines with bad clocks would be uniformly
+ *     distributed.  Unfortunately, in real life networks, the distribution
+ *     of machines is not uniform among models of machines, and the
+ *     distribution of errors in clocks tends to be quite consistent
+ *     for a given model.  In other words, all model VI Supre Servres
+ *     from GoFast Inc. tend to have about the same error.
+ *     The original BSD implementation would chose the clock of the
+ *     most common model, and discard all others.
+ *
+ *     Therefore, get best we can do is to try to average over all
+ *     of the machines in the network, while discarding "obviously"
+ *     bad values.
+ */
+long
+networkdelta()
+{
+       struct hosttbl *htp;
+       long med;
+       long lodelta, hidelta;
+       long logood, higood;
+       long x[NHOSTS];
+       long *xp;
+       int numdelta;
+       float eps;
+
+       /*
+        * compute the median of the good values
+        */
+       med = 0;
+       numdelta = 1;
+       xp = &x[0];
+       *xp = 0;                        /* account for ourself */
+       for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+               if (htp->good
+                   && htp->noanswer == 0
+                   && htp->delta != HOSTDOWN) {
+                       med += htp->delta;
+                       numdelta++;
+                       *++xp = htp->delta;
+               }
+       }
+
+       /*
+        * If we are the only trusted time keeper, then do not change our
+        * clock.  There may be another time keeping service active.
+        */
+       if (numdelta == 1)
+               return 0;
+
+       /* get average of trusted values */
+       med /= numdelta;
+
+       if (trace)
+               fprintf(fd, "median of %d values starting at %ld is about ",
+                       numdelta, med);
+       /* get median of all trusted values, using average as initial guess */
+       eps = med - x[0];
+       med = median(med, &eps, &x[0], xp+1, VALID_RANGE);
+
+       /* Compute the median of all good values.
+        * Good values are those of all clocks, including untrusted clocks,
+        * that are
+        *      - trusted and somewhat close to the median of the
+        *              trusted clocks
+        *      - trusted or untrusted and very close to the median of the
+        *              trusted clocks
+        */
+       hidelta = med + GOOD_RANGE;
+       lodelta = med - GOOD_RANGE;
+       higood = med + VGOOD_RANGE;
+       logood = med - VGOOD_RANGE;
+       xp = &x[0];
+       htp = &self;
+       do {
+               if (htp->noanswer == 0
+                   && htp->delta >= lodelta
+                   && htp->delta <= hidelta
+                   && (htp->good
+                       || (htp->delta >= logood
+                           && htp->delta <= higood))) {
+                       *xp++ = htp->delta;
+               }
+       } while (&self != (htp = htp->l_fwd));
+
+       if (xp == &x[0]) {
+               if (trace)
+                       fprintf(fd, "nothing close to median %ld\n", med);
+               return med;
+       }
+
+       if (xp == &x[1]) {
+               if (trace)
+                       fprintf(fd, "only value near median is %ld\n", x[0]);
+               return x[0];
+       }
+
+       if (trace)
+               fprintf(fd, "median of %d values starting at %ld is ",
+                       xp-&x[0], med);
+       return median(med, &eps, &x[0], xp, 1);
+}
+
+
+/*
+ * compute the median of an array of signed integers, using the idea
+ *     in <<Numerical Recipes>>.
+ */
+static long
+median(a0, eps_ptr, x, xlim, gnuf)
+       double a0;                      /* initial guess for the median */
+       float *eps_ptr;                 /* spacing near the median */
+       long *x, *xlim;                 /* the data */
+       unsigned int gnuf;              /* good enough estimate */
+{
+       long *xptr;
+       float a = a0;
+       float ap = LONG_MAX;            /* bounds on the median */
+       float am = -LONG_MAX;
+       float aa;
+       int npts;                       /* # of points above & below guess */
+       float xp;                       /* closet point above the guess */
+       float xm;                       /* closet point below the guess */
+       float eps;
+       float dum, sum, sumx;
+       int pass;
+#define AMP    1.5                     /* smoothing constants */
+#define AFAC   1.5
+
+       eps = *eps_ptr;
+       if (eps < 1.0) {
+               eps = -eps;
+               if (eps < 1.0)
+                       eps = 1.0;
+       }
+
+       for (pass = 1; ; pass++) {      /* loop over the data */
+               sum = 0.0;
+               sumx = 0.0;
+               npts = 0;
+               xp = LONG_MAX;
+               xm = -LONG_MAX;
+
+               for (xptr = x; xptr != xlim; xptr++) {
+                       float xx = *xptr;
+
+                       dum = xx - a;
+                       if (dum != 0.0) {   /* avoid dividing by 0 */
+                               if (dum > 0.0) {
+                                       npts++;
+                                       if (xx < xp)
+                                               xp = xx;
+                               } else {
+                                       npts--;
+                                       if (xx > xm)
+                                               xm = xx;
+                                       dum = -dum;
+                               }
+                               dum = 1.0/(eps + dum);
+                               sum += dum;
+                               sumx += xx * dum;
+                       }
+               }
+
+               if (ap-am < gnuf || sum == 0) {
+                       if (trace)
+                               fprintf(fd,
+                                       "%ld in %d passes;"
+                                       " early out balance=%d\n",
+                                       (long)a, pass, npts);
+                       return a;       /* guess was good enough */
+               }
+
+               aa = (sumx/sum-a)*AMP;
+               if (npts >= 2) {        /* guess was too low */
+                       am = a;
+                       aa = xp + max(0.0, aa);
+                       if (aa >= ap)
+                               aa = (a + ap)/2;
+
+               } else if (npts <= -2) {    /* guess was two high */
+                       ap = a;
+                       aa = xm + min(0.0, aa);
+                       if (aa <= am)
+                               aa = (a + am)/2;
+
+               } else {
+                       break;          /* got it */
+               }
+
+               if (a == aa) {
+                       if (trace)
+                               fprintf(fd, "%ld in %d passes;"
+                                       " force out balance=%d\n",
+                                       (long)a, pass, npts);
+                       return a;
+               }
+               eps = AFAC*abs(aa - a);
+               *eps_ptr = eps;
+               a = aa;
+       }
+
+       if (((x - xlim) % 2) != 0) {    /* even number of points? */
+               if (npts == 0)          /* yes, return an average */
+                       a = (xp+xm)/2;
+               else if (npts > 0)
+                       a =  (a+xp)/2;
+               else
+                       a = (xm+a)/2;
+
+       } else if (npts != 0) {         /* odd number of points */
+               if (npts > 0)
+                       a = xp;
+               else
+                       a = xm;
+       }
+
+       if (trace)
+               fprintf(fd, "%ld in %d passes\n", (long)a, pass);
+       return a;
+}
diff --git a/timed.tproj/timed.tproj/pathnames.h b/timed.tproj/timed.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..1a3faf3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#ifdef sgi
+#define        _PATH_MASTERLOG "/usr/adm/timed.masterlog"
+#define        _PATH_TIMEDLOG  "/usr/adm/timed.log"
+#else
+#define        _PATH_MASTERLOG "/var/log/timed.masterlog"
+#define        _PATH_TIMEDLOG  "/var/log/timed.log"
+#endif
diff --git a/timed.tproj/timed.tproj/readmsg.c b/timed.tproj/timed.tproj/readmsg.c
new file mode 100644 (file)
index 0000000..fab1e77
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)readmsg.c  8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+
+extern char *tsptype[];
+
+/*
+ * LOOKAT checks if the message is of the requested type and comes from
+ * the right machine, returning 1 in case of affirmative answer
+ */
+#define LOOKAT(msg, mtype, mfrom, netp, froms) \
+       (((mtype) == TSP_ANY || (mtype) == (msg).tsp_type) &&           \
+        ((mfrom) == 0 || !strcmp((mfrom), (msg).tsp_name)) &&          \
+        ((netp) == 0 ||                                                \
+         ((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net.s_addr))
+
+struct timeval rtime, rwait, rtout;
+struct tsp msgin;
+static struct tsplist {
+       struct tsp info;
+       struct timeval when;
+       struct sockaddr_in addr;
+       struct tsplist *p;
+} msgslist;
+struct sockaddr_in from;
+struct netinfo *fromnet;
+struct timeval from_when;
+
+/*
+ * `readmsg' returns message `type' sent by `machfrom' if it finds it
+ * either in the receive queue, or in a linked list of previously received
+ * messages that it maintains.
+ * Otherwise it waits to see if the appropriate message arrives within
+ * `intvl' seconds. If not, it returns NULL.
+ */
+
+struct tsp *
+readmsg(type, machfrom, intvl, netfrom)
+       int type;
+       char *machfrom;
+       struct timeval *intvl;
+       struct netinfo *netfrom;
+{
+       int length;
+       fd_set ready;
+       static struct tsplist *head = &msgslist;
+       static struct tsplist *tail = &msgslist;
+       static int msgcnt = 0;
+       struct tsplist *prev;
+       register struct netinfo *ntp;
+       register struct tsplist *ptr;
+
+       if (trace) {
+               fprintf(fd, "readmsg: looking for %s from %s, %s\n",
+                       tsptype[type], machfrom == NULL ? "ANY" : machfrom,
+                       netfrom == NULL ? "ANYNET" : inet_ntoa(netfrom->net));
+               if (head->p != 0) {
+                       length = 1;
+                       for (ptr = head->p; ptr != 0; ptr = ptr->p) {
+                               /* do not repeat the hundreds of messages */
+                               if (++length > 3) {
+                                       if (ptr == tail) {
+                                               fprintf(fd,"\t ...%d skipped\n",
+                                                       length);
+                                       } else {
+                                               continue;
+                                       }
+                               }
+                               fprintf(fd, length > 1 ? "\t" : "queue:\t");
+                               print(&ptr->info, &ptr->addr);
+                       }
+               }
+       }
+
+       ptr = head->p;
+       prev = head;
+
+       /*
+        * Look for the requested message scanning through the
+        * linked list. If found, return it and free the space
+        */
+
+       while (ptr != NULL) {
+               if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) {
+again:
+                       msgin = ptr->info;
+                       from = ptr->addr;
+                       from_when = ptr->when;
+                       prev->p = ptr->p;
+                       if (ptr == tail)
+                               tail = prev;
+                       free((char *)ptr);
+                       fromnet = NULL;
+                       if (netfrom == NULL)
+                           for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                                   if ((ntp->mask & from.sin_addr.s_addr) ==
+                                       ntp->net.s_addr) {
+                                           fromnet = ntp;
+                                           break;
+                                   }
+                           }
+                       else
+                           fromnet = netfrom;
+                       if (trace) {
+                               fprintf(fd, "readmsg: found ");
+                               print(&msgin, &from);
+                       }
+
+/* The protocol can get far behind.  When it does, it gets
+ *     hopelessly confused.  So delete duplicate messages.
+ */
+                       for (ptr = prev; (ptr = ptr->p) != NULL; prev = ptr) {
+                               if (ptr->addr.sin_addr.s_addr
+                                       == from.sin_addr.s_addr
+                                   && ptr->info.tsp_type == msgin.tsp_type) {
+                                       if (trace)
+                                               fprintf(fd, "\tdup ");
+                                       goto again;
+                               }
+                       }
+                       msgcnt--;
+                       return(&msgin);
+               } else {
+                       prev = ptr;
+                       ptr = ptr->p;
+               }
+       }
+
+       /*
+        * If the message was not in the linked list, it may still be
+        * coming from the network. Set the timer and wait
+        * on a select to read the next incoming message: if it is the
+        * right one, return it, otherwise insert it in the linked list.
+        */
+
+       (void)gettimeofday(&rtout, 0);
+       timevaladd(&rtout, intvl);
+       FD_ZERO(&ready);
+       for (;;) {
+               (void)gettimeofday(&rtime, 0);
+               timevalsub(&rwait, &rtout, &rtime);
+               if (rwait.tv_sec < 0)
+                       rwait.tv_sec = rwait.tv_usec = 0;
+               else if (rwait.tv_sec == 0
+                        && rwait.tv_usec < 1000000/CLK_TCK)
+                       rwait.tv_usec = 1000000/CLK_TCK;
+
+               if (trace) {
+                       fprintf(fd, "readmsg: wait %ld.%6ld at %s\n",
+                               rwait.tv_sec, rwait.tv_usec, date());
+                       /* Notice a full disk, as we flush trace info.
+                        * It is better to flush periodically than at
+                        * every line because the tracing consists of bursts
+                        * of many lines.  Without care, tracing slows
+                        * down the code enough to break the protocol.
+                        */
+                       if (rwait.tv_sec != 0
+                           && EOF == fflush(fd))
+                               traceoff("Tracing ended for cause at %s\n");
+               }
+
+               FD_SET(sock, &ready);
+               if (!select(sock+1, &ready, (fd_set *)0, (fd_set *)0,
+                          &rwait)) {
+                       if (rwait.tv_sec == 0 && rwait.tv_usec == 0)
+                               return(0);
+                       continue;
+               }
+               length = sizeof(from);
+               if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp), 0,
+                            (struct sockaddr*)&from, &length) < 0) {
+                       syslog(LOG_ERR, "recvfrom: %m");
+                       exit(1);
+               }
+               (void)gettimeofday(&from_when, (struct timezone *)0);
+               bytehostorder(&msgin);
+
+               if (msgin.tsp_vers > TSPVERSION) {
+                       if (trace) {
+                           fprintf(fd,"readmsg: version mismatch\n");
+                           /* should do a dump of the packet */
+                       }
+                       continue;
+               }
+
+               fromnet = NULL;
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+                       if ((ntp->mask & from.sin_addr.s_addr) ==
+                           ntp->net.s_addr) {
+                               fromnet = ntp;
+                               break;
+                       }
+
+               /*
+                * drop packets from nets we are ignoring permanently
+                */
+               if (fromnet == NULL) {
+                       /*
+                        * The following messages may originate on
+                        * this host with an ignored network address
+                        */
+                       if (msgin.tsp_type != TSP_TRACEON &&
+                           msgin.tsp_type != TSP_SETDATE &&
+                           msgin.tsp_type != TSP_MSITE &&
+                           msgin.tsp_type != TSP_TEST &&
+                           msgin.tsp_type != TSP_TRACEOFF) {
+                               if (trace) {
+                                   fprintf(fd,"readmsg: discard null net ");
+                                   print(&msgin, &from);
+                               }
+                               continue;
+                       }
+               }
+
+               /*
+                * Throw away messages coming from this machine,
+                * unless they are of some particular type.
+                * This gets rid of broadcast messages and reduces
+                * master processing time.
+                */
+               if (!strcmp(msgin.tsp_name, hostname)
+                   && msgin.tsp_type != TSP_SETDATE
+                   && msgin.tsp_type != TSP_TEST
+                   && msgin.tsp_type != TSP_MSITE
+                   && msgin.tsp_type != TSP_TRACEON
+                   && msgin.tsp_type != TSP_TRACEOFF
+                   && msgin.tsp_type != TSP_LOOP) {
+                       if (trace) {
+                               fprintf(fd, "readmsg: discard own ");
+                               print(&msgin, &from);
+                       }
+                       continue;
+               }
+
+               /*
+                * Send acknowledgements here; this is faster and
+                * avoids deadlocks that would occur if acks were
+                * sent from a higher level routine.  Different
+                * acknowledgements are necessary, depending on
+                * status.
+                */
+               if (fromnet == NULL)    /* do not de-reference 0 */
+                       ignoreack();
+               else if (fromnet->status == MASTER)
+                       masterack();
+               else if (fromnet->status == SLAVE)
+                       slaveack();
+               else
+                       ignoreack();
+
+               if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
+                       if (trace) {
+                               fprintf(fd, "readmsg: ");
+                               print(&msgin, &from);
+                       }
+                       return(&msgin);
+               } else if (++msgcnt > NHOSTS*3) {
+
+/* The protocol gets hopelessly confused if it gets too far
+*      behind.  However, it seems able to recover from all cases of lost
+*      packets.  Therefore, if we are swamped, throw everything away.
+*/
+                       if (trace)
+                               fprintf(fd,
+                                       "readmsg: discarding %d msgs\n",
+                                       msgcnt);
+                       msgcnt = 0;
+                       while ((ptr=head->p) != NULL) {
+                               head->p = ptr->p;
+                               free((char *)ptr);
+                       }
+                       tail = head;
+               } else {
+                       tail->p = (struct tsplist *)
+                                   malloc(sizeof(struct tsplist));
+                       tail = tail->p;
+                       tail->p = NULL;
+                       tail->info = msgin;
+                       tail->addr = from;
+                       /* timestamp msgs so SETTIMEs are correct */
+                       tail->when = from_when;
+               }
+       }
+}
+
+/*
+ * Send the necessary acknowledgements:
+ * only the type ACK is to be sent by a slave
+ */
+void
+slaveack()
+{
+       switch(msgin.tsp_type) {
+
+       case TSP_ADJTIME:
+       case TSP_SETTIME:
+       case TSP_ACCEPT:
+       case TSP_REFUSE:
+       case TSP_TRACEON:
+       case TSP_TRACEOFF:
+       case TSP_QUIT:
+               if (trace) {
+                       fprintf(fd, "Slaveack: ");
+                       print(&msgin, &from);
+               }
+               xmit(TSP_ACK,msgin.tsp_seq, &from);
+               break;
+
+       default:
+               if (trace) {
+                       fprintf(fd, "Slaveack: no ack: ");
+                       print(&msgin, &from);
+               }
+               break;
+       }
+}
+
+/*
+ * Certain packets may arrive from this machine on ignored networks.
+ * These packets should be acknowledged.
+ */
+void
+ignoreack()
+{
+       switch(msgin.tsp_type) {
+
+       case TSP_TRACEON:
+       case TSP_TRACEOFF:
+       case TSP_QUIT:
+               if (trace) {
+                       fprintf(fd, "Ignoreack: ");
+                       print(&msgin, &from);
+               }
+               xmit(TSP_ACK,msgin.tsp_seq, &from);
+               break;
+
+       default:
+               if (trace) {
+                       fprintf(fd, "Ignoreack: no ack: ");
+                       print(&msgin, &from);
+               }
+               break;
+       }
+}
+
+/*
+ * `masterack' sends the necessary acknowledgments
+ * to the messages received by a master
+ */
+void
+masterack()
+{
+       struct tsp resp;
+
+       resp = msgin;
+       resp.tsp_vers = TSPVERSION;
+       (void)strcpy(resp.tsp_name, hostname);
+
+       switch(msgin.tsp_type) {
+
+       case TSP_QUIT:
+       case TSP_TRACEON:
+       case TSP_TRACEOFF:
+       case TSP_MSITEREQ:
+               if (trace) {
+                       fprintf(fd, "Masterack: ");
+                       print(&msgin, &from);
+               }
+               xmit(TSP_ACK,msgin.tsp_seq, &from);
+               break;
+
+       case TSP_RESOLVE:
+       case TSP_MASTERREQ:
+               if (trace) {
+                       fprintf(fd, "Masterack: ");
+                       print(&msgin, &from);
+               }
+               xmit(TSP_MASTERACK,msgin.tsp_seq, &from);
+               break;
+
+       default:
+               if (trace) {
+                       fprintf(fd,"Masterack: no ack: ");
+                       print(&msgin, &from);
+               }
+               break;
+       }
+}
+
+/*
+ * Print a TSP message
+ */
+void
+print(msg, addr)
+       struct tsp *msg;
+       struct sockaddr_in *addr;
+{
+       char tm[26];
+       switch (msg->tsp_type) {
+
+       case TSP_LOOP:
+               fprintf(fd, "%s %d %-6u #%d %-15s %s\n",
+                       tsptype[msg->tsp_type],
+                       msg->tsp_vers,
+                       msg->tsp_seq,
+                       msg->tsp_hopcnt,
+                       inet_ntoa(addr->sin_addr),
+                       msg->tsp_name);
+               break;
+
+       case TSP_SETTIME:
+       case TSP_SETDATE:
+       case TSP_SETDATEREQ:
+#ifdef sgi
+               (void)cftime(tm, "%D %T", &msg->tsp_time.tv_sec);
+#else
+               strncpy(tm, ctime(&msg->tsp_time.tv_sec)+3+1, sizeof(tm));
+               tm[15] = '\0';          /* ugh */
+#endif /* sgi */
+               fprintf(fd, "%s %d %-6u %s %-15s %s\n",
+                       tsptype[msg->tsp_type],
+                       msg->tsp_vers,
+                       msg->tsp_seq,
+                       tm,
+                       inet_ntoa(addr->sin_addr),
+                       msg->tsp_name);
+               break;
+
+       case TSP_ADJTIME:
+               fprintf(fd, "%s %d %-6u (%ld,%ld) %-15s %s\n",
+                       tsptype[msg->tsp_type],
+                       msg->tsp_vers,
+                       msg->tsp_seq,
+                       msg->tsp_time.tv_sec,
+                       msg->tsp_time.tv_usec,
+                       inet_ntoa(addr->sin_addr),
+                       msg->tsp_name);
+               break;
+
+       default:
+               fprintf(fd, "%s %d %-6u %-15s %s\n",
+                       tsptype[msg->tsp_type],
+                       msg->tsp_vers,
+                       msg->tsp_seq,
+                       inet_ntoa(addr->sin_addr),
+                       msg->tsp_name);
+               break;
+       }
+}
diff --git a/timed.tproj/timed.tproj/slave.c b/timed.tproj/timed.tproj/slave.c
new file mode 100644 (file)
index 0000000..0b72058
--- /dev/null
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)slave.c    8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "globals.h"
+#include <setjmp.h>
+#include "pathnames.h"
+
+extern jmp_buf jmpenv;
+extern int Mflag;
+extern int justquit;
+
+extern u_short sequence;
+
+static char master_name[MAXHOSTNAMELEN+1];
+static struct netinfo *old_slavenet;
+static int old_status;
+
+static void schgdate __P((struct tsp *, char *));
+static void setmaster __P((struct tsp *));
+static void answerdelay __P((void));
+
+#ifdef sgi
+extern void logwtmp __P((struct timeval *, struct timeval *));
+#else
+extern void logwtmp __P((char *, char *, char *));
+#endif /* sgi */
+
+int
+slave()
+{
+       int tries;
+       long electiontime, refusetime, looktime, looptime, adjtime;
+       u_short seq;
+       long fastelection;
+#define FASTTOUT 3
+       struct in_addr cadr;
+       struct timeval otime;
+       struct sockaddr_in taddr;
+       char tname[MAXHOSTNAMELEN];
+       struct tsp *msg, to;
+       struct timeval ntime, wait;
+       struct tsp *answer;
+       int timeout();
+       char olddate[32];
+       char newdate[32];
+       struct netinfo *ntp;
+       struct hosttbl *htp;
+
+
+       old_slavenet = 0;
+       seq = 0;
+       refusetime = 0;
+       adjtime = 0;
+
+       (void)gettimeofday(&ntime, 0);
+       electiontime = ntime.tv_sec + delay2;
+       fastelection = ntime.tv_sec + FASTTOUT;
+       if (justquit)
+               looktime = electiontime;
+       else
+               looktime = fastelection;
+       looptime = fastelection;
+
+       if (slavenet)
+               xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr);
+       if (status & MASTER) {
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                       if (ntp->status == MASTER)
+                               masterup(ntp);
+               }
+       }
+
+loop:
+       get_goodgroup(0);
+       (void)gettimeofday(&ntime, (struct timezone *)0);
+       if (ntime.tv_sec > electiontime) {
+               if (trace)
+                       fprintf(fd, "election timer expired\n");
+               longjmp(jmpenv, 1);
+       }
+
+       if (ntime.tv_sec >= looktime) {
+               if (trace)
+                       fprintf(fd, "Looking for nets to master\n");
+
+               if (Mflag && nignorednets > 0) {
+                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                               if (ntp->status == IGNORE
+                                   || ntp->status == NOMASTER) {
+                                       lookformaster(ntp);
+                                       if (ntp->status == MASTER) {
+                                               masterup(ntp);
+                                       } else if (ntp->status == MASTER) {
+                                               ntp->status = NOMASTER;
+                                       }
+                               }
+                               if (ntp->status == MASTER
+                                   && --ntp->quit_count < 0)
+                                       ntp->quit_count = 0;
+                       }
+                       makeslave(slavenet);    /* prune extras */
+                       setstatus();
+               }
+               (void)gettimeofday(&ntime, 0);
+               looktime = ntime.tv_sec + delay2;
+       }
+       if (ntime.tv_sec >= looptime) {
+               if (trace)
+                       fprintf(fd, "Looking for loops\n");
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                   if (ntp->status == MASTER) {
+                       to.tsp_type = TSP_LOOP;
+                       to.tsp_vers = TSPVERSION;
+                       to.tsp_seq = sequence++;
+                       to.tsp_hopcnt = MAX_HOPCNT;
+                       (void)strcpy(to.tsp_name, hostname);
+                       bytenetorder(&to);
+                       if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
+                                  (struct sockaddr*)&ntp->dest_addr,
+                                  sizeof(ntp->dest_addr)) < 0) {
+                               trace_sendto_err(ntp->dest_addr.sin_addr);
+                       }
+                   }
+               }
+               (void)gettimeofday(&ntime, 0);
+               looptime = ntime.tv_sec + delay2;
+       }
+
+       wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec;
+       if (wait.tv_sec < 0)
+               wait.tv_sec = 0;
+       wait.tv_sec += FASTTOUT;
+       wait.tv_usec = 0;
+       msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
+
+       if (msg != NULL) {
+               /*
+                * filter stuff not for us
+                */
+               switch (msg->tsp_type) {
+               case TSP_SETDATE:
+               case TSP_TRACEOFF:
+               case TSP_TRACEON:
+                       /*
+                        * XXX check to see they are from ourself
+                        */
+                       break;
+
+               case TSP_TEST:
+               case TSP_MSITE:
+                       break;
+
+               case TSP_MASTERUP:
+                       if (!fromnet) {
+                               if (trace) {
+                                       fprintf(fd, "slave ignored: ");
+                                       print(msg, &from);
+                               }
+                               goto loop;
+                       }
+                       break;
+
+               default:
+                       if (!fromnet
+                           || fromnet->status == IGNORE
+                           || fromnet->status == NOMASTER) {
+                               if (trace) {
+                                       fprintf(fd, "slave ignored: ");
+                                       print(msg, &from);
+                               }
+                               goto loop;
+                       }
+                       break;
+               }
+
+
+               /*
+                * now process the message
+                */
+               switch (msg->tsp_type) {
+
+               case TSP_ADJTIME:
+                       if (fromnet != slavenet)
+                               break;
+                       if (!good_host_name(msg->tsp_name)) {
+                               syslog(LOG_NOTICE,
+                                  "attempted time adjustment by %s",
+                                      msg->tsp_name);
+                               suppress(&from, msg->tsp_name, fromnet);
+                               break;
+                       }
+                       /*
+                        * Speed up loop detection in case we have a loop.
+                        * Otherwise the clocks can race until the loop
+                        * is found.
+                        */
+                       (void)gettimeofday(&otime, 0);
+                       if (adjtime < otime.tv_sec)
+                               looptime -= (looptime-otime.tv_sec)/2 + 1;
+
+                       setmaster(msg);
+                       if (seq != msg->tsp_seq) {
+                               seq = msg->tsp_seq;
+                               synch(tvtomsround(msg->tsp_time));
+                       }
+                       (void)gettimeofday(&ntime, 0);
+                       electiontime = ntime.tv_sec + delay2;
+                       fastelection = ntime.tv_sec + FASTTOUT;
+                       adjtime = ntime.tv_sec + SAMPLEINTVL*2;
+                       break;
+
+               case TSP_SETTIME:
+                       if (fromnet != slavenet)
+                               break;
+                       if (seq == msg->tsp_seq)
+                               break;
+                       seq = msg->tsp_seq;
+
+                       /* adjust time for residence on the queue */
+                       (void)gettimeofday(&otime, 0);
+                       adj_msg_time(msg,&otime);
+#ifdef sgi
+                       (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+                       (void)cftime(olddate, "%D %T", &otime.tv_sec);
+#else
+                       /*
+                        * the following line is necessary due to syslog
+                        * calling ctime() which clobbers the static buffer
+                        */
+                       (void)strcpy(olddate, date());
+                       (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+
+                       if (!good_host_name(msg->tsp_name)) {
+                               syslog(LOG_NOTICE,
+                           "attempted time setting by untrusted %s to %s",
+                                      msg->tsp_name, newdate);
+                               suppress(&from, msg->tsp_name, fromnet);
+                               break;
+                       }
+
+                       setmaster(msg);
+                       timevalsub(&ntime, &msg->tsp_time, &otime);
+                       if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
+                               /*
+                                * do not change the clock if we can adjust it
+                                */
+                               synch(tvtomsround(ntime));
+                       } else {
+#ifdef sgi
+                               if (0 > settimeofday(&msg->tsp_time, 0)) {
+                                       syslog(LOG_ERR,"settimeofdate(): %m");
+                                       break;
+                               }
+                               logwtmp(&otime, &msg->tsp_time);
+#else
+                               logwtmp("|", "date", "");
+                               (void)settimeofday(&msg->tsp_time, 0);
+                               logwtmp("}", "date", "");
+#endif /* sgi */
+                               syslog(LOG_NOTICE,
+                                      "date changed by %s from %s",
+                                       msg->tsp_name, olddate);
+                               if (status & MASTER)
+                                       spreadtime();
+                       }
+                       (void)gettimeofday(&ntime, 0);
+                       electiontime = ntime.tv_sec + delay2;
+                       fastelection = ntime.tv_sec + FASTTOUT;
+
+/* This patches a bad protocol bug.  Imagine a system with several networks,
+ * where there are a pair of redundant gateways between a pair of networks,
+ * each running timed.  Assume that we start with a third machine mastering
+ * one of the networks, and one of the gateways mastering the other.
+ * Imagine that the third machine goes away and the non-master gateway
+ * decides to replace it.  If things are timed just 'right,' we will have
+ * each gateway mastering one network for a little while.  If a SETTIME
+ * message gets into the network at that time, perhaps from the newly
+ * masterful gateway as it was taking control, the SETTIME will loop
+ * forever.  Each time a gateway receives it on its slave side, it will
+ * call spreadtime to forward it on its mastered network.  We are now in
+ * a permanent loop, since the SETTIME msgs will keep any clock
+ * in the network from advancing.  Normally, the 'LOOP' stuff will detect
+ * and correct the situation.  However, with the clocks stopped, the
+ * 'looptime' timer cannot expire.  While they are in this state, the
+ * masters will try to saturate the network with SETTIME packets.
+ */
+                       looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1;
+                       break;
+
+               case TSP_MASTERUP:
+                       if (slavenet && fromnet != slavenet)
+                               break;
+                       if (!good_host_name(msg->tsp_name)) {
+                               suppress(&from, msg->tsp_name, fromnet);
+                               if (electiontime > fastelection)
+                                       electiontime = fastelection;
+                               break;
+                       }
+                       makeslave(fromnet);
+                       setmaster(msg);
+                       setstatus();
+                       answerdelay();
+                       xmit(TSP_SLAVEUP, 0, &from);
+                       (void)gettimeofday(&ntime, 0);
+                       electiontime = ntime.tv_sec + delay2;
+                       fastelection = ntime.tv_sec + FASTTOUT;
+                       refusetime = 0;
+                       break;
+
+               case TSP_MASTERREQ:
+                       if (fromnet->status != SLAVE)
+                               break;
+                       (void)gettimeofday(&ntime, 0);
+                       electiontime = ntime.tv_sec + delay2;
+                       break;
+
+               case TSP_SETDATE:
+#ifdef sgi
+                       (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+                       (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+                       schgdate(msg, newdate);
+                       break;
+
+               case TSP_SETDATEREQ:
+                       if (fromnet->status != MASTER)
+                               break;
+#ifdef sgi
+                       (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
+#else
+                       (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
+#endif /* sgi */
+                       htp = findhost(msg->tsp_name);
+                       if (0 == htp) {
+                               syslog(LOG_WARNING,
+                                      "DATEREQ from uncontrolled machine");
+                               break;
+                       }
+                       if (!htp->good) {
+                               syslog(LOG_WARNING,
+                               "attempted date change by untrusted %s to %s",
+                                      htp->name, newdate);
+                               spreadtime();
+                               break;
+                       }
+                       schgdate(msg, newdate);
+                       break;
+
+               case TSP_TRACEON:
+                       traceon();
+                       break;
+
+               case TSP_TRACEOFF:
+                       traceoff("Tracing ended at %s\n");
+                       break;
+
+               case TSP_SLAVEUP:
+                       newslave(msg);
+                       break;
+
+               case TSP_ELECTION:
+                       if (fromnet->status == SLAVE) {
+                               (void)gettimeofday(&ntime, 0);
+                               electiontime = ntime.tv_sec + delay2;
+                               fastelection = ntime.tv_sec + FASTTOUT;
+                               seq = 0;
+                               if (!good_host_name(msg->tsp_name)) {
+                                       syslog(LOG_NOTICE,
+                                              "suppress election of %s",
+                                              msg->tsp_name);
+                                       to.tsp_type = TSP_QUIT;
+                                       electiontime = fastelection;
+                               } else if (cadr.s_addr != from.sin_addr.s_addr
+                                          && ntime.tv_sec < refusetime) {
+/* if the candidate has to repeat itself, the old code would refuse it
+ * the second time.  That would prevent elections.
+ */
+                                       to.tsp_type = TSP_REFUSE;
+                               } else {
+                                       cadr.s_addr = from.sin_addr.s_addr;
+                                       to.tsp_type = TSP_ACCEPT;
+                                       refusetime = ntime.tv_sec + 30;
+                               }
+                               taddr = from;
+                               (void)strcpy(tname, msg->tsp_name);
+                               (void)strcpy(to.tsp_name, hostname);
+                               answerdelay();
+                               if (!acksend(&to, &taddr, tname,
+                                            TSP_ACK, 0, 0))
+                                       syslog(LOG_WARNING,
+                                            "no answer from candidate %s\n",
+                                              tname);
+
+                       } else {        /* fromnet->status == MASTER */
+                               htp = addmach(msg->tsp_name, &from,fromnet);
+                               to.tsp_type = TSP_QUIT;
+                               (void)strcpy(to.tsp_name, hostname);
+                               if (!acksend(&to, &htp->addr, htp->name,
+                                            TSP_ACK, 0, htp->noanswer)) {
+                                       syslog(LOG_ERR,
+                                         "no reply from %s to ELECTION-QUIT",
+                                              htp->name);
+                                       (void)remmach(htp);
+                               }
+                       }
+                       break;
+
+               case TSP_CONFLICT:
+                       if (fromnet->status != MASTER)
+                               break;
+                       /*
+                        * After a network partition, there can be
+                        * more than one master: the first slave to
+                        * come up will notify here the situation.
+                        */
+                       (void)strcpy(to.tsp_name, hostname);
+
+                       /* The other master often gets into the same state,
+                        * with boring results.
+                        */
+                       ntp = fromnet;  /* (acksend() can leave fromnet=0 */
+                       for (tries = 0; tries < 3; tries++) {
+                               to.tsp_type = TSP_RESOLVE;
+                               answer = acksend(&to, &ntp->dest_addr,
+                                                ANYADDR, TSP_MASTERACK,
+                                                ntp, 0);
+                               if (answer == NULL)
+                                       break;
+                               htp = addmach(answer->tsp_name,&from,ntp);
+                               to.tsp_type = TSP_QUIT;
+                               answer = acksend(&to, &htp->addr, htp->name,
+                                                TSP_ACK, 0, htp->noanswer);
+                               if (!answer) {
+                                       syslog(LOG_WARNING,
+                                 "conflict error: no reply from %s to QUIT",
+                                               htp->name);
+                                       (void)remmach(htp);
+                               }
+                       }
+                       masterup(ntp);
+                       break;
+
+               case TSP_MSITE:
+                       if (!slavenet)
+                               break;
+                       taddr = from;
+                       to.tsp_type = TSP_MSITEREQ;
+                       to.tsp_vers = TSPVERSION;
+                       to.tsp_seq = 0;
+                       (void)strcpy(to.tsp_name, hostname);
+                       answer = acksend(&to, &slavenet->dest_addr,
+                                        ANYADDR, TSP_ACK,
+                                        slavenet, 0);
+                       if (answer != NULL
+                           && good_host_name(answer->tsp_name)) {
+                               setmaster(answer);
+                               to.tsp_type = TSP_ACK;
+                               (void)strcpy(to.tsp_name, answer->tsp_name);
+                               bytenetorder(&to);
+                               if (sendto(sock, (char *)&to,
+                                          sizeof(struct tsp), 0,
+                                          (struct sockaddr*)&taddr, sizeof(taddr)) < 0) {
+                                       trace_sendto_err(taddr.sin_addr);
+                               }
+                       }
+                       break;
+
+               case TSP_MSITEREQ:
+                       break;
+
+               case TSP_ACCEPT:
+               case TSP_REFUSE:
+               case TSP_RESOLVE:
+                       break;
+
+               case TSP_QUIT:
+                       doquit(msg);            /* become a slave */
+                       break;
+
+               case TSP_TEST:
+                       electiontime = 0;
+                       break;
+
+               case TSP_LOOP:
+                       /* looking for loops of masters */
+                       if (!(status & MASTER))
+                               break;
+                       if (fromnet->status == SLAVE) {
+                           if (!strcmp(msg->tsp_name, hostname)) {
+                               /*
+                                * Someone forwarded our message back to
+                                * us.  There must be a loop.  Tell the
+                                * master of this network to quit.
+                                *
+                                * The other master often gets into
+                                * the same state, with boring results.
+                                */
+                               ntp = fromnet;
+                               for (tries = 0; tries < 3; tries++) {
+                                   to.tsp_type = TSP_RESOLVE;
+                                   answer = acksend(&to, &ntp->dest_addr,
+                                                    ANYADDR, TSP_MASTERACK,
+                                                    ntp,0);
+                                   if (answer == NULL)
+                                       break;
+                                   taddr = from;
+                                   (void)strcpy(tname, answer->tsp_name);
+                                   to.tsp_type = TSP_QUIT;
+                                   (void)strcpy(to.tsp_name, hostname);
+                                   if (!acksend(&to, &taddr, tname,
+                                                TSP_ACK, 0, 1)) {
+                                       syslog(LOG_ERR,
+                                       "no reply from %s to slave LOOP-QUIT",
+                                                tname);
+                                   } else {
+                                       electiontime = 0;
+                                   }
+                               }
+                               (void)gettimeofday(&ntime, 0);
+                               looptime = ntime.tv_sec + FASTTOUT;
+                           } else {
+                               if (msg->tsp_hopcnt-- < 1)
+                                   break;
+                               bytenetorder(msg);
+                               for (ntp = nettab; ntp != 0; ntp = ntp->next) {
+                                   if (ntp->status == MASTER
+                                       && 0 > sendto(sock, (char *)msg,
+                                                     sizeof(struct tsp), 0,
+                                             (struct sockaddr*)&ntp->dest_addr,
+                                                     sizeof(ntp->dest_addr)))
+                                   trace_sendto_err(ntp->dest_addr.sin_addr);
+                               }
+                           }
+                       } else {        /* fromnet->status == MASTER */
+                           /*
+                            * We should not have received this from a net
+                            * we are master on.  There must be two masters,
+                            * unless the packet was really from us.
+                            */
+                           if (from.sin_addr.s_addr
+                               == fromnet->my_addr.s_addr) {
+                               if (trace)
+                                   fprintf(fd,"discarding forwarded LOOP\n");
+                               break;
+                           }
+
+                           /*
+                            * The other master often gets into the same
+                            * state, with boring results.
+                            */
+                           ntp = fromnet;
+                           for (tries = 0; tries < 3; tries++) {
+                               to.tsp_type = TSP_RESOLVE;
+                               answer = acksend(&to, &ntp->dest_addr,
+                                                ANYADDR, TSP_MASTERACK,
+                                               ntp,0);
+                               if (!answer)
+                                       break;
+                               htp = addmach(answer->tsp_name,
+                                             &from,ntp);
+                               to.tsp_type = TSP_QUIT;
+                               (void)strcpy(to.tsp_name, hostname);
+                               if (!acksend(&to,&htp->addr,htp->name,
+                                            TSP_ACK, 0, htp->noanswer)) {
+                                       syslog(LOG_ERR,
+                                   "no reply from %s to master LOOP-QUIT",
+                                              htp->name);
+                                       (void)remmach(htp);
+                               }
+                           }
+                           (void)gettimeofday(&ntime, 0);
+                           looptime = ntime.tv_sec + FASTTOUT;
+                       }
+                       break;
+               default:
+                       if (trace) {
+                               fprintf(fd, "garbage message: ");
+                               print(msg, &from);
+                       }
+                       break;
+               }
+       }
+       goto loop;
+}
+
+
+/*
+ * tell the world who our master is
+ */
+static void
+setmaster(msg)
+       struct tsp *msg;
+{
+       if (slavenet
+           && (slavenet != old_slavenet
+               || strcmp(msg->tsp_name, master_name)
+               || old_status != status)) {
+               (void)strcpy(master_name, msg->tsp_name);
+               old_slavenet = slavenet;
+               old_status = status;
+
+               if (status & MASTER) {
+                       syslog(LOG_NOTICE, "submaster to %s", master_name);
+                       if (trace)
+                               fprintf(fd, "submaster to %s\n", master_name);
+
+               } else {
+                       syslog(LOG_NOTICE, "slave to %s", master_name);
+                       if (trace)
+                               fprintf(fd, "slave to %s\n", master_name);
+               }
+       }
+}
+
+
+
+/*
+ * handle date change request on a slave
+ */
+static void
+schgdate(msg, newdate)
+       struct tsp *msg;
+       char *newdate;
+{
+       struct tsp to;
+       u_short seq;
+       struct sockaddr_in taddr;
+       struct timeval otime;
+
+       if (!slavenet)
+               return;                 /* no where to forward */
+
+       taddr = from;
+       seq = msg->tsp_seq;
+
+       syslog(LOG_INFO,
+              "forwarding date change by %s to %s",
+              msg->tsp_name, newdate);
+
+       /* adjust time for residence on the queue */
+       (void)gettimeofday(&otime, 0);
+       adj_msg_time(msg, &otime);
+
+       to.tsp_type = TSP_SETDATEREQ;
+       to.tsp_time = msg->tsp_time;
+       (void)strcpy(to.tsp_name, hostname);
+       if (!acksend(&to, &slavenet->dest_addr,
+                    ANYADDR, TSP_DATEACK,
+                    slavenet, 0))
+               return;                 /* no answer */
+
+       xmit(TSP_DATEACK, seq, &taddr);
+}
+
+
+/*
+ * Used before answering a broadcast message to avoid network
+ * contention and likely collisions.
+ */
+static void
+answerdelay()
+{
+#ifdef sgi
+       sginap(delay1);
+#else
+       struct timeval timeout;
+
+       timeout.tv_sec = 0;
+       timeout.tv_usec = delay1;
+
+       (void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
+           &timeout);
+       return;
+#endif /* sgi */
+}
diff --git a/timed.tproj/timed.tproj/timed.8 b/timed.tproj/timed.tproj/timed.8
new file mode 100644 (file)
index 0000000..8f8798d
--- /dev/null
@@ -0,0 +1,219 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)timed.8    8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt TIMED 8
+.Os BSD 4.3
+.Sh NAME
+.Nm timed
+.Nd time server daemon
+.Sh SYNOPSIS
+.Nm timed
+.Op Fl M
+.Op Fl t
+.Op Fl d
+.Op Fl i Ar network
+.Op Fl n Ar network
+.Op Fl F Ar host1 host2 ...
+.Sh DESCRIPTION
+This
+is a time server daemon and is normally invoked
+at boot time from the
+.Xr rc 8
+file.  
+It synchronizes the host's time with the time of other
+machines in a local area network running 
+.Nm timed 8 .
+These time servers will slow down the clocks of some machines
+and speed up the clocks of others to bring them to the average network time.
+The average network time is computed from measurements of clock differences
+using the
+.Tn ICMP
+timestamp request message.
+.Pp
+The service provided by
+.Nm timed
+is based  on a master-slave
+scheme.
+When
+.Nm timed 8
+is started on a machine, it asks the master for the network time
+and sets the host's clock to that time.
+After that, it accepts synchronization messages periodically sent by
+the master and calls 
+.Xr adjtime 2
+to perform the needed corrections on the host's clock.
+.Pp
+It also communicates with
+.Xr date 1
+in order to set the date globally,
+and with 
+.Xr timedc 8 ,
+a timed control program.
+If the machine running the master crashes, then the slaves will elect
+a new master from among slaves running with the 
+.Fl M
+flag.
+A
+.Nm timed
+running without the
+.Fl M
+or
+.Fl F
+flags will remain a slave.
+The 
+.Fl t
+flag enables
+.Nm timed
+to trace the messages it receives in the
+file
+.Pa /var/log/timed.log .
+Tracing can be turned on or off by the program
+.Xr timedc 8 .
+The
+.Fl d
+flag is for debugging the daemon.
+It causes the program to not put itself into the background.
+Normally
+.Nm timed
+checks for a master time server on each network to which
+it is connected, except as modified by the options described below.
+It will request synchronization service from the first master server
+located.
+If permitted by the
+.Fl M
+flag, it will provide synchronization service on any attached networks
+on which no current master server was detected.
+Such a server propagates the time computed by the top-level master.
+The 
+.Fl n
+flag, followed by the name of a network which the host is connected to
+(see
+.Xr networks 5 ) ,
+overrides the default choice of the
+network addresses made by the program.
+Each time the
+.Fl n
+flag appears, that network name is added to a list of valid networks.
+All other networks are ignored.
+The 
+.Fl i
+flag, followed by the name of a network to which the host is connected
+(see
+.Xr networks 5 ) ,
+overrides the default choice of the network addresses made by the program.
+Each time the
+.Fl i
+flag appears, that network name is added to a list of networks to ignore.
+All other networks are used by the time daemon.
+The
+.Fl n
+and 
+.Fl i
+flags are meaningless if used together.
+.Pp
+.Nm Timed
+checks for a master time server on each network to which
+it is connected, except as modified by the
+.Fl n
+and
+.Fl i
+options described above.
+If it finds masters on more than one network, it chooses one network
+on which to be a "slave," and then periodically checks the other
+networks to see if the masters there have disappeared.
+.Pp
+One way to synchronize a group of machines is to use an NTP daemon to 
+synchronize the clock of one machine to a distant standard or a radio
+receiver and 
+.Fl F Ar hostname
+to tell its timed daemon to trust only itself.
+.Pp
+Messages printed by the kernel on the system console occur with
+interrupts disabled. 
+This means that the clock stops while they are printing.
+A machine with many disk or network hardware problems and consequent
+messages cannot keep good time by itself.  Each message typically causes
+the clock to lose a dozen milliseconds.  A time daemon can
+correct the result.
+.Pp
+Messages in the system log about machines that failed to respond
+usually indicate machines that crashed or were turned off.
+Complaints about machines that failed to respond to initial time
+settings are often associated with "multi-homed" machines
+that looked for time masters on more than one network and eventually
+chose to become a slave on the other network.
+.SH WARNING
+If two or more time daemons, whether 
+.Nm timed ,
+.Xr NTP ,
+try to adjust the same clock, temporal chaos will result.
+If both 
+.Nm
+and another time daemon are run on the same machine,
+ensure that the 
+.Fl F
+flag is used, so that 
+.Nm timed
+never attempts to adjust the local clock.
+.Pp 
+The protocol is based on UDP/IP broadcasts.  All machines within
+the range of a broadcast that are using the TSP protocol must cooperate.
+There cannot be more than a single administrative domain using the
+.Fl F
+flag among all machines reached by a broadcast packet.
+Failure to follow this rule is usually indicated by complaints concerning
+"untrusted" machines in the system log.
+.Sh FILES
+.Bl -tag -width /var/log/timed.masterlog -compact
+.It Pa /var/log/timed.log
+tracing file for timed
+.It Pa /var/log/timed.masterlog
+log file for master timed 
+.El
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr adjtime 2 ,
+.Xr gettimeofday 2 ,
+.Xr icmp 4 ,
+.Xr timedc 8 ,
+.Rs
+.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
+.%A R. Gusella
+.%A S. Zatti
+.Re
+.Sh HISTORY
+The
+.Nm
+daemon appeared in
+.Bx 4.3 .
diff --git a/timed.tproj/timed.tproj/timed.c b/timed.tproj/timed.tproj/timed.c
new file mode 100644 (file)
index 0000000..01fa981
--- /dev/null
@@ -0,0 +1,1006 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)timed.c    8.2 (Berkeley) 3/26/95";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif /* sgi */
+
+#define TSPTYPES
+#include "globals.h"
+#include <net/if.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <setjmp.h>
+#include "pathnames.h"
+#include <math.h>
+#include <sys/types.h>
+#include <sys/times.h>
+#ifdef sgi
+#include <unistd.h>
+#include <sys/syssgi.h>
+#include <sys/schedctl.h>
+#endif /* sgi */
+
+int trace = 0;
+int sock, sock_raw = -1;
+int status = 0;
+u_short sequence;                      /* sequence number */
+long delay1;
+long delay2;
+
+int nslavenets;                                /* nets were I could be a slave */
+int nmasternets;                       /* nets were I could be a master */
+int nignorednets;                      /* ignored nets */
+int nnets;                             /* nets I am connected to */
+
+FILE *fd;                              /* trace file FD */
+
+jmp_buf jmpenv;
+
+struct netinfo *nettab = 0;
+struct netinfo *slavenet;
+int Mflag;
+int justquit = 0;
+int debug;
+
+static struct nets {
+       char    *name;
+       long    net;
+       struct nets *next;
+} *nets = 0;
+
+struct hosttbl hosttbl[NHOSTS+1];      /* known hosts */
+
+static struct goodhost {               /* hosts that we trust */
+       char    name[MAXHOSTNAMELEN+1];
+       struct goodhost *next;
+       char    perm;
+} *goodhosts;
+
+static char *goodgroup;                        /* net group of trusted hosts */
+static void checkignorednets __P((void));
+static void pickslavenet __P((struct netinfo *));
+static void add_good_host __P((char *, int));
+
+#ifdef sgi
+char *timetrim_fn;
+char *timetrim_wpat = "long timetrim = %ld;\ndouble tot_adj = %.0f;\ndouble tot_ticks = %.0f;\n/* timed version 2 */\n";
+char *timetrim_rpat = "long timetrim = %ld;\ndouble tot_adj = %lf;\ndouble tot_ticks = %lf;";
+long timetrim;
+double tot_adj, hr_adj;                        /* totals in nsec */
+double tot_ticks, hr_ticks;
+
+int bufspace = 60*1024;
+#endif
+
+
+/*
+ * The timedaemons synchronize the clocks of hosts in a local area network.
+ * One daemon runs as master, all the others as slaves. The master
+ * performs the task of computing clock differences and sends correction
+ * values to the slaves.
+ * Slaves start an election to choose a new master when the latter disappears
+ * because of a machine crash, network partition, or when killed.
+ * A resolution protocol is used to kill all but one of the masters
+ * that happen to exist in segments of a partitioned network when the
+ * network partition is fixed.
+ *
+ * Authors: Riccardo Gusella & Stefano Zatti
+ *
+ * overhauled at Silicon Graphics
+ */
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int on;
+       int ret;
+       int nflag, iflag;
+       struct timeval ntime;
+       struct servent *srvp;
+       char buf[BUFSIZ], *cp, *cplim;
+       struct ifconf ifc;
+       struct ifreq ifreq, ifreqf, *ifr;
+       register struct netinfo *ntp;
+       struct netinfo *ntip;
+       struct netinfo *savefromnet;
+       struct netent *nentp;
+       struct nets *nt;
+       static struct sockaddr_in server;
+       u_short port;
+       char c;
+       extern char *optarg;
+       extern int optind, opterr;
+#ifdef sgi
+       FILE *timetrim_st;
+#endif
+
+#define        IN_MSG "timed: -i and -n make no sense together\n"
+#ifdef sgi
+       struct tms tms;
+#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp] [-P trimfile]\n"
+#else
+#ifdef HAVENIS
+#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp]\n"
+#else
+#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...]\n"
+#endif /* HAVENIS */
+#endif /* sgi */
+
+#ifdef lint
+       ntip = NULL;
+#endif
+
+       on = 1;
+       nflag = OFF;
+       iflag = OFF;
+
+#ifdef sgi
+       if (0 > syssgi(SGI_GETTIMETRIM, &timetrim)) {
+               perror("timed: syssgi(GETTIMETRIM)");
+               timetrim = 0;
+       }
+       tot_ticks = hr_ticks = times(&tms);
+#endif /* sgi */
+
+       opterr = 0;
+       while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != EOF) {
+               switch (c) {
+               case 'M':
+                       Mflag = 1;
+                       break;
+
+               case 't':
+                       trace = 1;
+                       break;
+
+               case 'n':
+                       if (iflag) {
+                               fprintf(stderr, IN_MSG);
+                               exit(1);
+                       } else {
+                               nflag = ON;
+                               addnetname(optarg);
+                       }
+                       break;
+
+               case 'i':
+                       if (nflag) {
+                               fprintf(stderr, IN_MSG);
+                               exit(1);
+                       } else {
+                               iflag = ON;
+                               addnetname(optarg);
+                       }
+                       break;
+
+               case 'F':
+                       add_good_host(optarg,1);
+                       while (optind < argc && argv[optind][0] != '-')
+                               add_good_host(argv[optind++], 1);
+                       break;
+
+               case 'd':
+                       debug = 1;
+                       break;
+               case 'G':
+                       if (goodgroup != 0) {
+                               fprintf(stderr,"timed: only one net group\n");
+                               exit(1);
+                       }
+                       goodgroup = optarg;
+                       break;
+#ifdef sgi
+               case 'P':
+                       timetrim_fn = optarg;
+                       break;
+#endif /* sgi */
+
+               default:
+                       fprintf(stderr, USAGE);
+                       exit(1);
+                       break;
+               }
+       }
+       if (optind < argc) {
+               fprintf(stderr, USAGE);
+               exit(1);
+       }
+
+#ifdef sgi
+       if (timetrim_fn == 0) {
+               ;
+       } else if (0 == (timetrim_st = fopen(timetrim_fn, "r+"))) {
+               if (errno != ENOENT) {
+                       (void)fprintf(stderr,"timed: ");
+                       perror(timetrim_fn);
+                       timetrim_fn = 0;
+               }
+       } else {
+               int i;
+               long trim;
+               double adj, ticks;
+
+               i = fscanf(timetrim_st, timetrim_rpat,
+                          &trim, &adj, &ticks);
+               if (i < 1
+                   || trim > MAX_TRIM
+                   || trim < -MAX_TRIM
+                   || i == 2
+                   || (i == 3
+                       && trim != rint(adj*CLK_TCK/ticks))) {
+                       if (trace && i != EOF)
+                               (void)fprintf(stderr,
+                   "timed: unrecognized contents in %s\n",
+                                             timetrim_fn);
+               } else {
+                       if (0 > syssgi(SGI_SETTIMETRIM,
+                                      trim)) {
+                        perror("timed: syssgi(SETTIMETRIM)");
+                       } else {
+                               timetrim = trim;
+                       }
+                       if (i == 3)
+                               tot_ticks -= ticks;
+               }
+               (void)fclose(timetrim_st);
+       }
+#endif /* sgi */
+
+       /* If we care about which machine is the master, then we must
+        *      be willing to be a master
+        */
+       if (0 != goodgroup || 0 != goodhosts)
+               Mflag = 1;
+
+       if (gethostname(hostname, sizeof(hostname) - 1) < 0) {
+               perror("gethostname");
+               exit(1);
+       }
+       self.l_bak = &self;
+       self.l_fwd = &self;
+       self.h_bak = &self;
+       self.h_fwd = &self;
+       self.head = 1;
+       self.good = 1;
+
+       if (goodhosts != 0)             /* trust ourself */
+               add_good_host(hostname,1);
+
+       srvp = getservbyname("timed", "udp");
+       if (srvp == 0) {
+               fprintf(stderr, "unknown service 'timed/udp'\n");
+               exit(1);
+       }
+       port = srvp->s_port;
+       server.sin_addr.s_addr = INADDR_ANY;
+       server.sin_port = srvp->s_port;
+       server.sin_family = AF_INET;
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock < 0) {
+               perror("socket");
+               exit(1);
+       }
+       if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on,
+                                                       sizeof(on)) < 0) {
+               perror("setsockopt");
+               exit(1);
+       }
+       if (bind(sock, (struct sockaddr*)&server, sizeof(server))) {
+               if (errno == EADDRINUSE)
+                       fprintf(stderr,"timed: time daemon already running\n");
+               else
+                       perror("bind");
+               exit(1);
+       }
+#ifdef sgi
+       /*
+        * handle many slaves with our buffer
+        */
+       if (0 > setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace,
+                        sizeof(bufspace))) {
+               perror("setsockopt");
+               exit(1);
+       }
+#endif /* sgi */
+
+       /* choose a unique seed for random number generation */
+       (void)gettimeofday(&ntime, 0);
+       srandom(ntime.tv_sec + ntime.tv_usec);
+
+       sequence = random();     /* initial seq number */
+
+#ifndef sgi
+       /* rounds kernel variable time to multiple of 5 ms. */
+       ntime.tv_sec = 0;
+       ntime.tv_usec = -((ntime.tv_usec/1000) % 5) * 1000;
+       (void)adjtime(&ntime, (struct timeval *)0);
+#endif /* sgi */
+
+       for (nt = nets; nt; nt = nt->next) {
+               nentp = getnetbyname(nt->name);
+               if (nentp == 0) {
+                       nt->net = inet_network(nt->name);
+                       if (nt->net != INADDR_NONE)
+                               nentp = getnetbyaddr(nt->net, AF_INET);
+               }
+               if (nentp != 0) {
+                       nt->net = nentp->n_net;
+               } else if (nt->net == INADDR_NONE) {
+                       fprintf(stderr, "timed: unknown net %s\n", nt->name);
+                       exit(1);
+               } else if (nt->net == INADDR_ANY) {
+                       fprintf(stderr, "timed: bad net %s\n", nt->name);
+                       exit(1);
+               } else {
+                       fprintf(stderr,
+                               "timed: warning: %s unknown in /etc/networks\n",
+                               nt->name);
+               }
+
+               if (0 == (nt->net & 0xff000000))
+                   nt->net <<= 8;
+               if (0 == (nt->net & 0xff000000))
+                   nt->net <<= 8;
+               if (0 == (nt->net & 0xff000000))
+                   nt->net <<= 8;
+       }
+       ifc.ifc_len = sizeof(buf);
+       ifc.ifc_buf = buf;
+       if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+               perror("timed: get interface configuration");
+               exit(1);
+       }
+       ntp = NULL;
+#ifdef sgi
+#define size(p)        (sizeof(*ifr) - sizeof(ifr->ifr_name))  /* XXX hack. kludge */
+#else
+#define size(p)        max((p).sa_len, sizeof(p))
+#endif
+       cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+       for (cp = buf; cp < cplim;
+                       cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
+               ifr = (struct ifreq *)cp;
+               if (ifr->ifr_addr.sa_family != AF_INET)
+                       continue;
+               if (!ntp)
+                       ntp = (struct netinfo*)malloc(sizeof(struct netinfo));
+               bzero(ntp,sizeof(*ntp));
+               ntp->my_addr=((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
+               ntp->status = NOMASTER;
+               ifreq = *ifr;
+               ifreqf = *ifr;
+
+               if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreqf) < 0) {
+                       perror("get interface flags");
+                       continue;
+               }
+               if ((ifreqf.ifr_flags & IFF_UP) == 0)
+                       continue;
+               if ((ifreqf.ifr_flags & IFF_BROADCAST) == 0 &&
+                   (ifreqf.ifr_flags & IFF_POINTOPOINT) == 0) {
+                       continue;
+               }
+
+
+               if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
+                       perror("get netmask");
+                       continue;
+               }
+               ntp->mask = ((struct sockaddr_in *)
+                       &ifreq.ifr_addr)->sin_addr.s_addr;
+
+               if (ifreqf.ifr_flags & IFF_BROADCAST) {
+                       if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+                               perror("get broadaddr");
+                               continue;
+                       }
+                       ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
+                       /* What if the broadcast address is all ones?
+                        * So we cannot just mask ntp->dest_addr.  */
+                       ntp->net = ntp->my_addr;
+                       ntp->net.s_addr &= ntp->mask;
+               } else {
+                       if (ioctl(sock, SIOCGIFDSTADDR,
+                                               (char *)&ifreq) < 0) {
+                               perror("get destaddr");
+                               continue;
+                       }
+                       ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr;
+                       ntp->net = ntp->dest_addr.sin_addr;
+               }
+
+               ntp->dest_addr.sin_port = port;
+
+               for (nt = nets; nt; nt = nt->next) {
+                       if (ntp->net.s_addr == nt->net)
+                               break;
+               }
+               if (nflag && !nt || iflag && nt)
+                       continue;
+
+               ntp->next = NULL;
+               if (nettab == NULL) {
+                       nettab = ntp;
+               } else {
+                       ntip->next = ntp;
+               }
+               ntip = ntp;
+               ntp = NULL;
+       }
+       if (ntp)
+               (void) free((char *)ntp);
+       if (nettab == NULL) {
+               fprintf(stderr, "timed: no network usable\n");
+               exit(1);
+       }
+
+
+#ifdef sgi
+       (void)schedctl(RENICE,0,10);       /* run fast to get good time */
+
+       /* ticks to delay before responding to a broadcast */
+       delay1 = casual(0, CLK_TCK/10);
+#else
+
+       /* microseconds to delay before responding to a broadcast */
+       delay1 = casual(1, 100*1000);
+#endif /* sgi */
+
+       /* election timer delay in secs. */
+       delay2 = casual(MINTOUT, MAXTOUT);
+
+
+#ifdef sgi
+       (void)_daemonize(debug ? _DF_NOFORK|_DF_NOCHDIR : 0, sock, -1, -1);
+#else
+       if (!debug)
+               daemon(debug, 0);
+#endif /* sgi */
+
+       if (trace)
+               traceon();
+       openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON);
+
+       /*
+        * keep returning here
+        */
+       ret = setjmp(jmpenv);
+       savefromnet = fromnet;
+       setstatus();
+
+       if (Mflag) {
+               switch (ret) {
+
+               case 0:
+                       checkignorednets();
+                       pickslavenet(0);
+                       break;
+               case 1:
+                       /* Just lost our master */
+                       if (slavenet != 0)
+                               slavenet->status = election(slavenet);
+                       if (!slavenet || slavenet->status == MASTER) {
+                               checkignorednets();
+                               pickslavenet(0);
+                       } else {
+                               makeslave(slavenet);    /* prune extras */
+                       }
+                       break;
+
+               case 2:
+                       /* Just been told to quit */
+                       justquit = 1;
+                       pickslavenet(savefromnet);
+                       break;
+               }
+
+               setstatus();
+               if (!(status & MASTER) && sock_raw != -1) {
+                       /* sock_raw is not being used now */
+                       (void)close(sock_raw);
+                       sock_raw = -1;
+               }
+
+               if (status == MASTER)
+                       master();
+               else
+                       slave();
+
+       } else {
+               if (sock_raw != -1) {
+                       (void)close(sock_raw);
+                       sock_raw = -1;
+               }
+
+               if (ret) {
+                       /* we just lost our master or were told to quit */
+                       justquit = 1;
+               }
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                       if (ntp->status == MASTER)
+                               rmnetmachs(ntp);
+                               ntp->status = NOMASTER;
+               }
+               checkignorednets();
+               pickslavenet(0);
+               setstatus();
+
+               slave();
+       }
+       /* NOTREACHED */
+#ifdef lint
+       return(0);
+#endif
+}
+
+/*
+ * suppress an upstart, untrustworthy, self-appointed master
+ */
+void
+suppress(addr, name,net)
+       struct sockaddr_in *addr;
+       char *name;
+       struct netinfo *net;
+{
+       struct sockaddr_in tgt;
+       char tname[MAXHOSTNAMELEN];
+       struct tsp msg;
+       static struct timeval wait;
+
+       if (trace)
+               fprintf(fd, "suppress: %s\n", name);
+       tgt = *addr;
+       (void)strcpy(tname, name);
+
+       while (0 != readmsg(TSP_ANY, ANYADDR, &wait, net)) {
+               if (trace)
+                       fprintf(fd, "suppress:\tdiscarded packet from %s\n",
+                                   name);
+       }
+
+       syslog(LOG_NOTICE, "suppressing false master %s", tname);
+       msg.tsp_type = TSP_QUIT;
+       (void)strcpy(msg.tsp_name, hostname);
+       (void)acksend(&msg, &tgt, tname, TSP_ACK, 0, 1);
+}
+
+void
+lookformaster(ntp)
+       struct netinfo *ntp;
+{
+       struct tsp resp, conflict, *answer;
+       struct timeval ntime;
+       char mastername[MAXHOSTNAMELEN];
+       struct sockaddr_in masteraddr;
+
+       get_goodgroup(0);
+       ntp->status = SLAVE;
+
+       /* look for master */
+       resp.tsp_type = TSP_MASTERREQ;
+       (void)strcpy(resp.tsp_name, hostname);
+       answer = acksend(&resp, &ntp->dest_addr, ANYADDR,
+                        TSP_MASTERACK, ntp, 0);
+       if (answer != 0 && !good_host_name(answer->tsp_name)) {
+               suppress(&from, answer->tsp_name, ntp);
+               ntp->status = NOMASTER;
+               answer = 0;
+       }
+       if (answer == 0) {
+               /*
+                * Various conditions can cause conflict: races between
+                * two just started timedaemons when no master is
+                * present, or timedaemons started during an election.
+                * A conservative approach is taken.  Give up and became a
+                * slave, postponing election of a master until first
+                * timer expires.
+                */
+               ntime.tv_sec = ntime.tv_usec = 0;
+               answer = readmsg(TSP_MASTERREQ, ANYADDR, &ntime, ntp);
+               if (answer != 0) {
+                       if (!good_host_name(answer->tsp_name)) {
+                               suppress(&from, answer->tsp_name, ntp);
+                               ntp->status = NOMASTER;
+                       }
+                       return;
+               }
+
+               ntime.tv_sec = ntime.tv_usec = 0;
+               answer = readmsg(TSP_MASTERUP, ANYADDR, &ntime, ntp);
+               if (answer != 0) {
+                       if (!good_host_name(answer->tsp_name)) {
+                               suppress(&from, answer->tsp_name, ntp);
+                               ntp->status = NOMASTER;
+                       }
+                       return;
+               }
+
+               ntime.tv_sec = ntime.tv_usec = 0;
+               answer = readmsg(TSP_ELECTION, ANYADDR, &ntime, ntp);
+               if (answer != 0) {
+                       if (!good_host_name(answer->tsp_name)) {
+                               suppress(&from, answer->tsp_name, ntp);
+                               ntp->status = NOMASTER;
+                       }
+                       return;
+               }
+
+               if (Mflag)
+                       ntp->status = MASTER;
+               else
+                       ntp->status = NOMASTER;
+               return;
+       }
+
+       ntp->status = SLAVE;
+       (void)strcpy(mastername, answer->tsp_name);
+       masteraddr = from;
+
+       /*
+        * If network has been partitioned, there might be other
+        * masters; tell the one we have just acknowledged that
+        * it has to gain control over the others.
+        */
+       ntime.tv_sec = 0;
+       ntime.tv_usec = 300000;
+       answer = readmsg(TSP_MASTERACK, ANYADDR, &ntime, ntp);
+       /*
+        * checking also not to send CONFLICT to ack'ed master
+        * due to duplicated MASTERACKs
+        */
+       if (answer != NULL &&
+           strcmp(answer->tsp_name, mastername) != 0) {
+               conflict.tsp_type = TSP_CONFLICT;
+               (void)strcpy(conflict.tsp_name, hostname);
+               if (!acksend(&conflict, &masteraddr, mastername,
+                            TSP_ACK, 0, 0)) {
+                       syslog(LOG_ERR,
+                              "error on sending TSP_CONFLICT");
+               }
+       }
+}
+
+/*
+ * based on the current network configuration, set the status, and count
+ * networks;
+ */
+void
+setstatus()
+{
+       struct netinfo *ntp;
+
+       status = 0;
+       nmasternets = nslavenets = nnets = nignorednets = 0;
+       if (trace)
+               fprintf(fd, "Net status:\n");
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+               switch ((int)ntp->status) {
+               case MASTER:
+                       nmasternets++;
+                       break;
+               case SLAVE:
+                       nslavenets++;
+                       break;
+               case NOMASTER:
+               case IGNORE:
+                       nignorednets++;
+                       break;
+               }
+               if (trace) {
+                       fprintf(fd, "\t%-16s", inet_ntoa(ntp->net));
+                       switch ((int)ntp->status) {
+                       case NOMASTER:
+                               fprintf(fd, "NOMASTER\n");
+                               break;
+                       case MASTER:
+                               fprintf(fd, "MASTER\n");
+                               break;
+                       case SLAVE:
+                               fprintf(fd, "SLAVE\n");
+                               break;
+                       case IGNORE:
+                               fprintf(fd, "IGNORE\n");
+                               break;
+                       default:
+                               fprintf(fd, "invalid state %d\n",
+                                       (int)ntp->status);
+                               break;
+                       }
+               }
+               nnets++;
+               status |= ntp->status;
+       }
+       status &= ~IGNORE;
+       if (trace)
+               fprintf(fd,
+                       "\tnets=%d masters=%d slaves=%d ignored=%d delay2=%d\n",
+                       nnets, nmasternets, nslavenets, nignorednets, delay2);
+}
+
+void
+makeslave(net)
+       struct netinfo *net;
+{
+       register struct netinfo *ntp;
+
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+               if (ntp->status == SLAVE && ntp != net)
+                       ntp->status = IGNORE;
+       }
+       slavenet = net;
+}
+
+/*
+ * Try to become master over ignored nets..
+ */
+static void
+checkignorednets()
+{
+       register struct netinfo *ntp;
+
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+               if (!Mflag && ntp->status == SLAVE)
+                       break;
+
+               if (ntp->status == IGNORE || ntp->status == NOMASTER) {
+                       lookformaster(ntp);
+                       if (!Mflag && ntp->status == SLAVE)
+                               break;
+               }
+       }
+}
+
+/*
+ * choose a good network on which to be a slave
+ *     The ignored networks must have already been checked.
+ *     Take a hint about for a good network.
+ */
+static void
+pickslavenet(ntp)
+       struct netinfo *ntp;
+{
+       if (slavenet != 0 && slavenet->status == SLAVE) {
+               makeslave(slavenet);            /* prune extras */
+               return;
+       }
+
+       if (ntp == 0 || ntp->status != SLAVE) {
+               for (ntp = nettab; ntp != 0; ntp = ntp->next) {
+                       if (ntp->status == SLAVE)
+                               break;
+               }
+       }
+       makeslave(ntp);
+}
+
+/*
+ * returns a random number in the range [inf, sup]
+ */
+long
+casual(inf, sup)
+       long inf, sup;
+{
+       double value;
+
+       value = ((double)(random() & 0x7fffffff)) / (0x7fffffff*1.0);
+       return(inf + (sup - inf)*value);
+}
+
+char *
+date()
+{
+#ifdef sgi
+       struct  timeval tv;
+       static char tm[32];
+
+       (void)gettimeofday(&tv, (struct timezone *)0);
+       (void)cftime(tm, "%D %T", &tv.tv_sec);
+       return (tm);
+#else
+       struct  timeval tv;
+
+       (void)gettimeofday(&tv, (struct timezone *)0);
+       return (ctime(&tv.tv_sec));
+#endif /* sgi */
+}
+
+void
+addnetname(name)
+       char *name;
+{
+       register struct nets **netlist = &nets;
+
+       while (*netlist)
+               netlist = &((*netlist)->next);
+       *netlist = (struct nets *)malloc(sizeof **netlist);
+       if (*netlist == 0) {
+               fprintf(stderr,"malloc failed\n");
+               exit(1);
+       }
+       bzero((char *)*netlist, sizeof(**netlist));
+       (*netlist)->name = name;
+}
+
+/* note a host as trustworthy */
+static void
+add_good_host(name, perm)
+       char *name;
+       int perm;                       /* 1=not part of the netgroup */
+{
+       register struct goodhost *ghp;
+       register struct hostent *hentp;
+
+       ghp = (struct goodhost*)malloc(sizeof(*ghp));
+       if (!ghp) {
+               syslog(LOG_ERR, "malloc failed");
+               exit(1);
+       }
+
+       bzero((char*)ghp, sizeof(*ghp));
+       (void)strncpy(&ghp->name[0], name, sizeof(ghp->name));
+       ghp->next = goodhosts;
+       ghp->perm = perm;
+       goodhosts = ghp;
+
+       hentp = gethostbyname(name);
+       if (0 == hentp && perm)
+               (void)fprintf(stderr, "unknown host %s\n", name);
+}
+
+
+/* update our image of the net-group of trustworthy hosts
+ */
+void
+get_goodgroup(force)
+       int force;
+{
+# define NG_DELAY (30*60*CLK_TCK)      /* 30 minutes */
+       static unsigned long last_update = -NG_DELAY;
+       unsigned long new_update;
+       struct hosttbl *htp;
+       struct goodhost *ghp, **ghpp;
+       char *mach, *usr, *dom;
+       struct tms tm;
+
+
+       /* if no netgroup, then we are finished */
+       if (goodgroup == 0 || !Mflag)
+               return;
+
+       /* Do not chatter with the netgroup master too often.
+        */
+       new_update = times(&tm);
+       if (new_update < last_update + NG_DELAY
+           && !force)
+               return;
+       last_update = new_update;
+
+       /* forget the old temporary entries */
+       ghpp = &goodhosts;
+       while (0 != (ghp = *ghpp)) {
+               if (!ghp->perm) {
+                       *ghpp = ghp->next;
+                       free((char*)ghp);
+               } else {
+                       ghpp = &ghp->next;
+               }
+       }
+
+#ifdef HAVENIS
+       /* quit now if we are not one of the trusted masters
+        */
+       if (!innetgr(goodgroup, &hostname[0], 0,0)) {
+               if (trace)
+                       (void)fprintf(fd, "get_goodgroup: %s not in %s\n",
+                                     &hostname[0], goodgroup);
+               return;
+       }
+       if (trace)
+               (void)fprintf(fd, "get_goodgroup: %s in %s\n",
+                                 &hostname[0], goodgroup);
+
+       /* mark the entire netgroup as trusted */
+       (void)setnetgrent(goodgroup);
+       while (getnetgrent(&mach,&usr,&dom)) {
+               if (0 != mach)
+                       add_good_host(mach,0);
+       }
+       (void)endnetgrent();
+
+       /* update list of slaves */
+       for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
+               htp->good = good_host_name(&htp->name[0]);
+       }
+#endif /* HAVENIS */
+}
+
+
+/* see if a machine is trustworthy
+ */
+int                                    /* 1=trust hp to change our date */
+good_host_name(name)
+       char *name;
+{
+       register struct goodhost *ghp = goodhosts;
+       register char c;
+
+       if (!ghp || !Mflag)             /* trust everyone if no one named */
+               return 1;
+
+       c = *name;
+       do {
+               if (c == ghp->name[0]
+                   && !strcasecmp(name, ghp->name))
+                       return 1;       /* found him, so say so */
+       } while (0 != (ghp = ghp->next));
+
+       if (!strcasecmp(name,hostname)) /* trust ourself */
+               return 1;
+
+       return 0;                       /* did not find him */
+}
diff --git a/timed.tproj/timedc.tproj/Makefile b/timed.tproj/timedc.tproj/Makefile
new file mode 100644 (file)
index 0000000..ae13f3a
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = timedc
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h timedc.h
+
+CFILES = cmds.c cmdtab.c timedc.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
+            h.template
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD/$(NAME)
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/timed.tproj/timedc.tproj/Makefile.postamble b/timed.tproj/timedc.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7b861e1
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+VPATH += :../timed.tproj
diff --git a/timed.tproj/timedc.tproj/Makefile.preamble b/timed.tproj/timedc.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..b5b8eac
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = byteorder.o measure.o cksum.o
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/timed.tproj/timedc.tproj/PB.project b/timed.tproj/timedc.tproj/PB.project
new file mode 100644 (file)
index 0000000..a4a35bf
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (extern.h, timedc.h); 
+        OTHER_LINKED = (cmds.c, cmdtab.c, timedc.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD/$(NAME)"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = timedc; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/timed.tproj/timedc.tproj/cmds.c b/timed.tproj/timedc.tproj/cmds.c
new file mode 100644 (file)
index 0000000..a844190
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmds.c     8.2 (Berkeley) 3/26/95";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "timedc.h"
+#include <sys/file.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#define TSPTYPES
+#include <protocols/timed.h>
+
+#ifdef sgi
+#include <bstring.h>
+#include <sys/clock.h>
+#else
+#define        SECHR   (60*60)
+#define        SECDAY  (24*SECHR)
+#endif /* sgi */
+
+# define DATE_PROTO "udp"
+# define DATE_PORT "time"
+
+
+int sock;
+int sock_raw;
+char myname[MAXHOSTNAMELEN];
+struct hostent *hp;
+struct sockaddr_in server;
+struct sockaddr_in dayaddr;
+extern int measure_delta;
+
+void bytenetorder(struct tsp *);
+void bytehostorder(struct tsp *);
+
+
+#define BU ((unsigned long)2208988800) /* seconds before UNIX epoch */
+
+
+/* compute the difference between our date and another machine
+ */
+static int                             /* difference in days from our time */
+daydiff(hostname)
+       char *hostname;
+{
+       int i;
+       int trials;
+       struct timeval tout, now;
+       fd_set ready;
+       struct sockaddr from;
+       int fromlen;
+       unsigned long sec;
+
+
+       /* wait 2 seconds between 10 tries */
+       tout.tv_sec = 2;
+       tout.tv_usec = 0;
+       for (trials = 0; trials < 10; trials++) {
+               /* ask for the time */
+               sec = 0;
+               if (sendto(sock, &sec, sizeof(sec), 0,
+                          (struct sockaddr*)&dayaddr, sizeof(dayaddr)) < 0) {
+                       perror("sendto(sock)");
+                       return 0;
+               }
+
+               for (;;) {
+                       FD_ZERO(&ready);
+                       FD_SET(sock, &ready);
+                       i = select(sock+1, &ready, (fd_set *)0,
+                                  (fd_set *)0, &tout);
+                       if (i < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                               perror("select(date read)");
+                               return 0;
+                       }
+                       if (0 == i)
+                               break;
+
+                       fromlen = sizeof(from);
+                       if (recvfrom(sock,&sec,sizeof(sec),0,
+                                    &from,&fromlen) < 0) {
+                               perror("recvfrom(date read)");
+                               return 0;
+                       }
+
+                       sec = ntohl(sec);
+                       if (sec < BU) {
+                               fprintf(stderr,
+                                       "%s says it is before 1970: %lu",
+                                       hostname, sec);
+                               return 0;
+                       }
+                       sec -= BU;
+
+                       (void)gettimeofday(&now, (struct timezone*)0);
+                       return (sec - now.tv_sec);
+               }
+       }
+
+       /* if we get here, we tried too many times */
+       fprintf(stderr,"%s will not tell us the date\n", hostname);
+       return 0;
+}
+
+
+/*
+ * Clockdiff computes the difference between the time of the machine on
+ * which it is called and the time of the machines given as argument.
+ * The time differences measured by clockdiff are obtained using a sequence
+ * of ICMP TSTAMP messages which are returned to the sender by the IP module
+ * in the remote machine.
+ * In order to compare clocks of machines in different time zones, the time
+ * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
+ * If a hosts uses a different time format, it should set the high order
+ * bit of the 32-bit quantity it transmits.
+ * However, VMS apparently transmits the time in milliseconds since midnight
+ * local time (rather than GMT) without setting the high order bit.
+ * Furthermore, it does not understand daylight-saving time.  This makes
+ * clockdiff behaving inconsistently with hosts running VMS.
+ *
+ * In order to reduce the sensitivity to the variance of message transmission
+ * time, clockdiff sends a sequence of messages.  Yet, measures between
+ * two `distant' hosts can be affected by a small error. The error can,
+ * however, be reduced by increasing the number of messages sent in each
+ * measurement.
+ */
+void
+clockdiff(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int measure_status;
+       extern int measure(u_long, u_long, char *, struct sockaddr_in*, int);
+       register int avg_cnt;
+       register long avg;
+       struct servent *sp;
+
+       if (argc < 2)  {
+               printf("Usage: clockdiff host ... \n");
+               return;
+       }
+
+       (void)gethostname(myname,sizeof(myname));
+
+       /* get the address for the date ready */
+       sp = getservbyname(DATE_PORT, DATE_PROTO);
+       if (!sp) {
+               (void)fprintf(stderr, "%s/%s is an unknown service\n",
+                             DATE_PORT, DATE_PROTO);
+               dayaddr.sin_port = 0;
+       } else {
+               dayaddr.sin_port = sp->s_port;
+       }
+
+       while (argc > 1) {
+               argc--; argv++;
+               hp = gethostbyname(*argv);
+               if (hp == NULL) {
+                       fprintf(stderr, "timedc: %s: ", *argv);
+                       herror(0);
+                       continue;
+               }
+
+               server.sin_family = hp->h_addrtype;
+               bcopy(hp->h_addr, &server.sin_addr.s_addr, hp->h_length);
+               for (avg_cnt = 0, avg = 0; avg_cnt < 16; avg_cnt++) {
+                       measure_status = measure(10000,100, *argv, &server, 1);
+                       if (measure_status != GOOD)
+                               break;
+                       avg += measure_delta;
+               }
+               if (measure_status == GOOD)
+                       measure_delta = avg/avg_cnt;
+
+               switch (measure_status) {
+               case HOSTDOWN:
+                       printf("%s is down\n", hp->h_name);
+                       continue;
+               case NONSTDTIME:
+                       printf("%s transmitts a non-standard time format\n",
+                              hp->h_name);
+                       continue;
+               case UNREACHABLE:
+                       printf("%s is unreachable\n", hp->h_name);
+                       continue;
+               }
+
+               /*
+                * Try to get the date only after using ICMP timestamps to
+                * get the time.  This is because the date protocol
+                * is optional.
+                */
+               if (dayaddr.sin_port != 0) {
+                       dayaddr.sin_family = hp->h_addrtype;
+                       bcopy(hp->h_addr, &dayaddr.sin_addr.s_addr,
+                             hp->h_length);
+                       avg = daydiff(*argv);
+                       if (avg > SECDAY) {
+                               printf("time on %s is %ld days ahead %s\n",
+                                      hp->h_name, avg/SECDAY, myname);
+                               continue;
+                       } else if (avg < -SECDAY) {
+                               printf("time on %s is %ld days behind %s\n",
+                                      hp->h_name, -avg/SECDAY, myname);
+                               continue;
+                       }
+               }
+
+               if (measure_delta > 0) {
+                       printf("time on %s is %d ms. ahead of time on %s\n",
+                              hp->h_name, measure_delta, myname);
+               } else if (measure_delta == 0) {
+                       printf("%s and %s have the same time\n",
+                              hp->h_name, myname);
+               } else {
+                       printf("time on %s is %d ms. behind time on %s\n",
+                              hp->h_name, -measure_delta, myname);
+               }
+       }
+       return;
+}
+
+
+/*
+ * finds location of master timedaemon
+ */
+void
+msite(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int cc;
+       fd_set ready;
+       struct sockaddr_in dest;
+       int i, length;
+       struct sockaddr from;
+       struct timeval tout;
+       struct tsp msg;
+       struct servent *srvp;
+       char *tgtname;
+
+       if (argc < 1) {
+               printf("Usage: msite [hostname]\n");
+               return;
+       }
+
+       srvp = getservbyname("timed", "udp");
+       if (srvp == 0) {
+               fprintf(stderr, "udp/timed: unknown service\n");
+               return;
+       }
+       dest.sin_port = srvp->s_port;
+       dest.sin_family = AF_INET;
+
+       (void)gethostname(myname, sizeof(myname));
+       i = 1;
+       do {
+               tgtname = (i >= argc) ? myname : argv[i];
+               hp = gethostbyname(tgtname);
+               if (hp == 0) {
+                       fprintf(stderr, "timedc: %s: ", tgtname);
+                       herror(0);
+                       continue;
+               }
+               bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
+
+               (void)strcpy(msg.tsp_name, myname);
+               msg.tsp_type = TSP_MSITE;
+               msg.tsp_vers = TSPVERSION;
+               bytenetorder(&msg);
+               if (sendto(sock, &msg, sizeof(struct tsp), 0,
+                          (struct sockaddr*)&dest,
+                          sizeof(struct sockaddr)) < 0) {
+                       perror("sendto");
+                       continue;
+               }
+
+               tout.tv_sec = 15;
+               tout.tv_usec = 0;
+               FD_ZERO(&ready);
+               FD_SET(sock, &ready);
+               if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
+                          &tout)) {
+                       length = sizeof(struct sockaddr);
+                       cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
+                                     &from, &length);
+                       if (cc < 0) {
+                               perror("recvfrom");
+                               continue;
+                       }
+                       bytehostorder(&msg);
+                       if (msg.tsp_type == TSP_ACK) {
+                               printf("master timedaemon at %s is %s\n",
+                                      tgtname, msg.tsp_name);
+                       } else {
+                               printf("received wrong ack: %s\n",
+                                      tsptype[msg.tsp_type]);
+                       }
+               } else {
+                       printf("communication error with %s\n", tgtname);
+               }
+       } while (++i < argc);
+}
+
+/*
+ * quits timedc
+ */
+void
+quit()
+{
+       exit(0);
+}
+
+
+/*
+ * Causes the election timer to expire on the selected hosts
+ * It sends just one udp message per machine, relying on
+ * reliability of communication channel.
+ */
+void
+testing(argc, argv)
+       int argc;
+       char *argv[];
+{
+       struct servent *srvp;
+       struct sockaddr_in sin;
+       struct tsp msg;
+
+       if (argc < 2)  {
+               printf("Usage: election host1 [host2 ...]\n");
+               return;
+       }
+
+       srvp = getservbyname("timed", "udp");
+       if (srvp == 0) {
+               fprintf(stderr, "udp/timed: unknown service\n");
+               return;
+       }
+
+       while (argc > 1) {
+               argc--; argv++;
+               hp = gethostbyname(*argv);
+               if (hp == NULL) {
+                       fprintf(stderr, "timedc: %s: ", *argv);
+                       herror(0);
+                       argc--; argv++;
+                       continue;
+               }
+               sin.sin_port = srvp->s_port;
+               sin.sin_family = hp->h_addrtype;
+               bcopy(hp->h_addr, &sin.sin_addr.s_addr, hp->h_length);
+
+               msg.tsp_type = TSP_TEST;
+               msg.tsp_vers = TSPVERSION;
+               (void)gethostname(myname, sizeof(myname));
+               (void)strncpy(msg.tsp_name, myname, sizeof(msg.tsp_name));
+               bytenetorder(&msg);
+               if (sendto(sock, &msg, sizeof(struct tsp), 0,
+                          (struct sockaddr*)&sin,
+                          sizeof(struct sockaddr)) < 0) {
+                       perror("sendto");
+               }
+       }
+}
+
+
+/*
+ * Enables or disables tracing on local timedaemon
+ */
+void
+tracing(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int onflag;
+       int length;
+       int cc;
+       fd_set ready;
+       struct sockaddr_in dest;
+       struct sockaddr from;
+       struct timeval tout;
+       struct tsp msg;
+       struct servent *srvp;
+
+       if (argc != 2) {
+               printf("Usage: tracing { on | off }\n");
+               return;
+       }
+
+       srvp = getservbyname("timed", "udp");
+       if (srvp == 0) {
+               fprintf(stderr, "udp/timed: unknown service\n");
+               return;
+       }
+       dest.sin_port = srvp->s_port;
+       dest.sin_family = AF_INET;
+
+       (void)gethostname(myname,sizeof(myname));
+       hp = gethostbyname(myname);
+       bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
+
+       if (strcmp(argv[1], "on") == 0) {
+               msg.tsp_type = TSP_TRACEON;
+               onflag = ON;
+       } else {
+               msg.tsp_type = TSP_TRACEOFF;
+               onflag = OFF;
+       }
+
+       (void)strcpy(msg.tsp_name, myname);
+       msg.tsp_vers = TSPVERSION;
+       bytenetorder(&msg);
+       if (sendto(sock, &msg, sizeof(struct tsp), 0,
+                  (struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0) {
+               perror("sendto");
+               return;
+       }
+
+       tout.tv_sec = 5;
+       tout.tv_usec = 0;
+       FD_ZERO(&ready);
+       FD_SET(sock, &ready);
+       if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
+               length = sizeof(struct sockaddr);
+               cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
+                             &from, &length);
+               if (cc < 0) {
+                       perror("recvfrom");
+                       return;
+               }
+               bytehostorder(&msg);
+               if (msg.tsp_type == TSP_ACK)
+                       if (onflag)
+                               printf("timed tracing enabled\n");
+                       else
+                               printf("timed tracing disabled\n");
+               else
+                       printf("wrong ack received: %s\n",
+                                               tsptype[msg.tsp_type]);
+       } else
+               printf("communication error\n");
+}
+
+int
+priv_resources()
+{
+       int port;
+       struct sockaddr_in sin;
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock < 0) {
+               perror("opening socket");
+               return(-1);
+       }
+
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = 0;
+       for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
+               sin.sin_port = htons((u_short)port);
+               if (bind(sock, (struct sockaddr*)&sin, sizeof (sin)) >= 0)
+                       break;
+               if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
+                       perror("bind");
+                       (void) close(sock);
+                       return(-1);
+               }
+       }
+       if (port == IPPORT_RESERVED / 2) {
+               fprintf(stderr, "all reserved ports in use\n");
+               (void) close(sock);
+               return(-1);
+       }
+
+       sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+       if (sock_raw < 0)  {
+               perror("opening raw socket");
+               (void) close(sock);
+               return(-1);
+       }
+       return(1);
+}
diff --git a/timed.tproj/timedc.tproj/cmdtab.c b/timed.tproj/timedc.tproj/cmdtab.c
new file mode 100644 (file)
index 0000000..546a206
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cmdtab.c   8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include "timedc.h"
+
+char   clockdiffhelp[] =       "measures clock differences between machines";
+char   helphelp[] =            "gets help on commands";
+char   msitehelp[] =           "finds location of master";
+char   quithelp[] =            "exits timedc";
+char   testinghelp[] =         "causes election timers to expire";
+char   tracinghelp[] =         "turns tracing on or off";
+
+struct cmd cmdtab[] = {
+       { "clockdiff",  clockdiffhelp,  clockdiff,      0 },
+       { "election",   testinghelp,    testing,        1 },
+       { "help",       helphelp,       help,           0 },
+       { "msite",      msitehelp,      msite,          0 },
+       { "quit",       quithelp,       quit,           0 },
+       { "trace",      tracinghelp,    tracing,        1 },
+       { "?",          helphelp,       help,           0 },
+};
+
+int    NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]);
diff --git a/timed.tproj/timedc.tproj/extern.h b/timed.tproj/timedc.tproj/extern.h
new file mode 100644 (file)
index 0000000..22e2e29
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)extern.h    8.1 (Berkeley) 6/6/93
+ */
+
+#if __STDC__
+struct tsp;
+#endif
+
+extern struct cmd cmdtab[];
+
+void   bytehostorder __P((struct tsp *));
+void   bytenetorder __P((struct tsp *));
+void   clockdiff __P((int, char *[]));
+void   help __P((int, char *[]));
+void   intr __P((int));
+void   makeargv __P((void));
+void   msite __P((int, char *[]));
+int    priv_resources __P((void));
+void   quit __P((void));
+void   testing __P((int, char *[]));
+void   tracing __P((int, char *[]));
diff --git a/timed.tproj/timedc.tproj/h.template b/timed.tproj/timedc.tproj/h.template
new file mode 100644 (file)
index 0000000..f3c1b04
--- /dev/null
@@ -0,0 +1,11 @@
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
diff --git a/timed.tproj/timedc.tproj/m.template b/timed.tproj/timedc.tproj/m.template
new file mode 100644 (file)
index 0000000..1216fe5
--- /dev/null
@@ -0,0 +1,18 @@
+$$ Lines starting with $$ are not inserted into newly created files
+$$ The following substitutions are made:
+$$
+$$ $FILENAME$                e.g. foo.m
+$$ $FILENAMESANSEXTENSION$   e.g. foo
+$$ $DIRECTORY$               e.g. /tmp/MyNewApp
+$$ $PROJECTNAME$             e.g. MyNewApp
+$$ $SUBPROJECTNAME$          e.g. TheGoodPart.subproj
+$$ $USERNAME$                e.g. mwagner
+$$ $DATE$                    e.g. Jan-1-1994
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import "$FILENAMESANSEXTENSION$.h"
+
+@implementation $FILENAMESANSEXTENSION$
+
+@end
diff --git a/timed.tproj/timedc.tproj/timedc.c b/timed.tproj/timedc.tproj/timedc.c
new file mode 100644 (file)
index 0000000..63e2884
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)timedc.c   8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#ifdef sgi
+#ident "$Revision: 1.1.1.1 $"
+#endif
+
+#include "timedc.h"
+#include <strings.h>
+#include <signal.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+int trace = 0;
+FILE *fd = 0;
+int    margc;
+int    fromatty;
+char   *margv[20];
+char   cmdline[200];
+jmp_buf        toplevel;
+static struct cmd *getcmd __P((char *));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct cmd *c;
+
+       openlog("timedc", LOG_ODELAY, LOG_AUTH);
+
+       /*
+        * security dictates!
+        */
+       if (priv_resources() < 0) {
+               fprintf(stderr, "Could not get privileged resources\n");
+               exit(1);
+       }
+       (void) setuid(getuid());
+
+       if (--argc > 0) {
+               c = getcmd(*++argv);
+               if (c == (struct cmd *)-1) {
+                       printf("?Ambiguous command\n");
+                       exit(1);
+               }
+               if (c == 0) {
+                       printf("?Invalid command\n");
+                       exit(1);
+               }
+               if (c->c_priv && getuid()) {
+                       printf("?Privileged command\n");
+                       exit(1);
+               }
+               (*c->c_handler)(argc, argv);
+               exit(0);
+       }
+
+       fromatty = isatty(fileno(stdin));
+       if (setjmp(toplevel))
+               putchar('\n');
+       (void) signal(SIGINT, intr);
+       for (;;) {
+               if (fromatty) {
+                       printf("timedc> ");
+                       (void) fflush(stdout);
+               }
+               if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
+                       quit();
+               if (cmdline[0] == 0)
+                       break;
+               makeargv();
+               if (margv[0] == 0)
+                       continue;
+               c = getcmd(margv[0]);
+               if (c == (struct cmd *)-1) {
+                       printf("?Ambiguous command\n");
+                       continue;
+               }
+               if (c == 0) {
+                       printf("?Invalid command\n");
+                       continue;
+               }
+               if (c->c_priv && getuid()) {
+                       printf("?Privileged command\n");
+                       continue;
+               }
+               (*c->c_handler)(margc, margv);
+       }
+       return 0;
+}
+
+void
+intr(signo)
+       int signo;
+{
+       if (!fromatty)
+               exit(0);
+       longjmp(toplevel, 1);
+}
+
+
+static struct cmd *
+getcmd(name)
+       char *name;
+{
+       register char *p, *q;
+       register struct cmd *c, *found;
+       register int nmatches, longest;
+       extern int NCMDS;
+
+       longest = 0;
+       nmatches = 0;
+       found = 0;
+       for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+               p = c->c_name;
+               for (q = name; *q == *p++; q++)
+                       if (*q == 0)            /* exact match? */
+                               return(c);
+               if (!*q) {                      /* the name was a prefix */
+                       if (q - name > longest) {
+                               longest = q - name;
+                               nmatches = 1;
+                               found = c;
+                       } else if (q - name == longest)
+                               nmatches++;
+               }
+       }
+       if (nmatches > 1)
+               return((struct cmd *)-1);
+       return(found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+void
+makeargv()
+{
+       register char *cp;
+       register char **argp = margv;
+
+       margc = 0;
+       for (cp = cmdline; *cp;) {
+               while (isspace(*cp))
+                       cp++;
+               if (*cp == '\0')
+                       break;
+               *argp++ = cp;
+               margc += 1;
+               while (*cp != '\0' && !isspace(*cp))
+                       cp++;
+               if (*cp == '\0')
+                       break;
+               *cp++ = '\0';
+       }
+       *argp++ = 0;
+}
+
+#define HELPINDENT (sizeof ("directory"))
+
+/*
+ * Help command.
+ */
+void
+help(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct cmd *c;
+
+       if (argc == 1) {
+               register int i, j, w;
+               int columns, width = 0, lines;
+               extern int NCMDS;
+
+               printf("Commands may be abbreviated.  Commands are:\n\n");
+               for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+                       int len = strlen(c->c_name);
+
+                       if (len > width)
+                               width = len;
+               }
+               width = (width + 8) &~ 7;
+               columns = 80 / width;
+               if (columns == 0)
+                       columns = 1;
+               lines = (NCMDS + columns - 1) / columns;
+               for (i = 0; i < lines; i++) {
+                       for (j = 0; j < columns; j++) {
+                               c = cmdtab + j * lines + i;
+                               printf("%s", c->c_name);
+                               if (c + lines >= &cmdtab[NCMDS]) {
+                                       printf("\n");
+                                       break;
+                               }
+                               w = strlen(c->c_name);
+                               while (w < width) {
+                                       w = (w + 8) &~ 7;
+                                       putchar('\t');
+                               }
+                       }
+               }
+               return;
+       }
+       while (--argc > 0) {
+               register char *arg;
+               arg = *++argv;
+               c = getcmd(arg);
+               if (c == (struct cmd *)-1)
+                       printf("?Ambiguous help command %s\n", arg);
+               else if (c == (struct cmd *)0)
+                       printf("?Invalid help command %s\n", arg);
+               else
+                       printf("%-*s\t%s\n", (int)HELPINDENT,
+                               c->c_name, c->c_help);
+       }
+}
diff --git a/timed.tproj/timedc.tproj/timedc.h b/timed.tproj/timedc.tproj/timedc.h
new file mode 100644 (file)
index 0000000..43ca72c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)timedc.h    8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#ifdef sgi
+#include <sys/uio.h>
+#endif
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+
+extern int errno;
+
+#define ON             1
+#define OFF            0
+
+#define GOOD           1
+#define UNREACHABLE    2
+#define NONSTDTIME     3
+#define HOSTDOWN       0x7fffffff
+
+struct cmd {
+       char    *c_name;                /* command name */
+       char    *c_help;                /* help message */
+       void    (*c_handler)();         /* routine to do the work */
+       int     c_priv;                 /* privileged command */
+};
+
+#include "extern.h"
diff --git a/traceroute.tproj/Makefile b/traceroute.tproj/Makefile
new file mode 100644 (file)
index 0000000..75c293b
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = traceroute
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = traceroute.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble mean.awk\
+            median.awk README traceroute.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/traceroute.tproj/Makefile.postamble b/traceroute.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..de54c24
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+INSTALL_PERMISSIONS = 4555        # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
diff --git a/traceroute.tproj/Makefile.preamble b/traceroute.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2c9003c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/traceroute.tproj/PB.project b/traceroute.tproj/PB.project
new file mode 100644 (file)
index 0000000..a843e7e
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (traceroute.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            mean.awk, 
+            median.awk, 
+            README, 
+            traceroute.8
+        ); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = traceroute; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/traceroute.tproj/README b/traceroute.tproj/README
new file mode 100644 (file)
index 0000000..6d33c6c
--- /dev/null
@@ -0,0 +1,126 @@
+Tue Dec 27 06:24:24 PST 1988
+
+Traceroute is a system administrators utility to trace the route
+ip packets from the current system take in getting to some
+destination system.  See the comments at the front of the
+program for a description of its use.
+
+This program 
+
+ a) can only be run by root (it uses raw ip sockets).
+
+ b) REQUIRES A KERNEL MOD to the raw ip output code to run.
+
+If you want to hack on your kernel, my modified version of the
+routine rip_output (in file /sys/netinet/raw_ip.c) is attached.
+This code may or may not resemble the code in your kernel.
+It may offer you a place to start but I make no promises.
+If you do hack your kernel, remember to test everything that uses
+raw ip sockets (e.g., ping and egpup/gated) & make sure they still
+work.  I wish you the best of luck and you're on your own.
+
+If your system has the ttl bug mentioned in the source, you
+might want to fix it while you're in the kernel.  (This bug
+appears in all releases of BSD up to but not including 4.3tahoe.
+If your version of netinet/ip_icmp.c is any earlier than 7.3
+(April, '87), it has the bug.)  The fix is just to add the line
+       ip->ip_ttl = MAXTTL;
+after the line
+       ip->ip_src = t;
+(or anywhere before the call to icmp_send) in routine icmp_reflect.
+
+If you're running this on a pre-4.3bsd system (e.g., Sun 3.x,
+Ultrix) that strips ip headers from icmp messages, add -DARCHAIC
+to CFLAGS in the Makefile.  Also note that rip_output contains
+a conditional for a 4.2/4.3 change in the location of a raw
+socket's protocol number.  I've checked this under 4.3 & Sun OS
+3.5 but you should double-check your system to make sure the
+appropriate branch of the #if is taken (check the line that
+assigned to ip->ip_p in your system's original rip_output).
+
+A couple of awk programs to massage the traceroute output are
+included.  "mean.awk" and "median.awk" compute the mean and median
+time to each hop, respectively.  I've found that something like
+
+       traceroute -q 7 foo.somewhere >t
+       awk -f median.awk t | graph
+
+can give you a quick picture of the bad spots on a long
+path (median is usually a better noise filter than mean).
+
+Enjoy.
+
+ - Van Jacobson (van@helios.ee.lbl.gov)
+
+-------------------- rip_output from /sys/netinet/raw_ip.c
+rip_output(m, so)
+       register struct mbuf *m;
+       struct socket *so;
+{
+       register struct ip *ip;
+       int error;
+       struct rawcb *rp = sotorawcb(so);
+       struct sockaddr_in *sin;
+#if BSD>=43
+       short proto = rp->rcb_proto.sp_protocol;
+#else
+       short proto = so->so_proto->pr_protocol;
+#endif
+       /*
+        * if the protocol is IPPROTO_RAW, the user handed us a 
+        * complete IP packet.  Otherwise, allocate an mbuf for a
+        * header and fill it in as needed.
+        */
+       if (proto != IPPROTO_RAW) {
+               /*
+                * Calculate data length and get an mbuf
+                * for IP header.
+                */
+               int len = 0;
+               struct mbuf *m0;
+
+               for (m0 = m; m; m = m->m_next)
+                       len += m->m_len;
+
+               m = m_get(M_DONTWAIT, MT_HEADER);
+               if (m == 0) {
+                       m = m0;
+                       error = ENOBUFS;
+                       goto bad;
+               }
+               m->m_off = MMAXOFF - sizeof(struct ip);
+               m->m_len = sizeof(struct ip);
+               m->m_next = m0;
+
+               ip = mtod(m, struct ip *);
+               ip->ip_tos = 0;
+               ip->ip_off = 0;
+               ip->ip_p = proto;
+               ip->ip_len = sizeof(struct ip) + len;
+               ip->ip_ttl = MAXTTL;
+       } else
+               ip = mtod(m, struct ip *);
+
+       if (rp->rcb_flags & RAW_LADDR) {
+               sin = (struct sockaddr_in *)&rp->rcb_laddr;
+               if (sin->sin_family != AF_INET) {
+                       error = EAFNOSUPPORT;
+                       goto bad;
+               }
+               ip->ip_src.s_addr = sin->sin_addr.s_addr;
+       } else
+               ip->ip_src.s_addr = 0;
+
+       ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr;
+
+#if BSD>=43
+       return (ip_output(m, rp->rcb_options, &rp->rcb_route, 
+          (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST));
+#else
+       return (ip_output(m, (struct mbuf *)0, &rp->rcb_route, 
+          (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST));
+#endif
+bad:
+       m_freem(m);
+       return (error);
+}
diff --git a/traceroute.tproj/mean.awk b/traceroute.tproj/mean.awk
new file mode 100644 (file)
index 0000000..e97a56f
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/awk -f
+#
+# Copyright (c) 1990, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Van Jacobson.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#      @(#)mean.awk    8.1 (Berkeley) 6/6/93
+#
+/^ *[0-9]/     {
+       # print out the average time to each hop along a route.
+       tottime = 0; n = 0;
+       for (f = 5; f <= NF; ++f) {
+               if ($f == "ms") {
+                       tottime += $(f - 1)
+                       ++n
+               }
+       }
+       if (n > 0)
+               print $1, tottime/n, median
+}
diff --git a/traceroute.tproj/median.awk b/traceroute.tproj/median.awk
new file mode 100644 (file)
index 0000000..1a8d81d
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/awk -f
+#
+# Copyright (c) 1990, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Van Jacobson.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#      @(#)median.awk  8.1 (Berkeley) 6/6/93
+#
+/^ *[0-9]/     {
+       # print out the median time to each hop along a route.
+       tottime = 0; n = 0;
+       for (f = 5; f <= NF; ++f) {
+               if ($f == "ms") {
+                       ++n
+                       time[n] = $(f - 1)
+               }
+       }
+       if (n > 0) {
+               # insertion sort the times to find the median
+               for (i = 2; i <= n; ++i) {
+                       v = time[i]; j = i - 1;
+                       while (time[j] > v) {
+                               time[j+1] = time[j];
+                               j = j - 1;
+                               if (j < 0)
+                                       break;
+                       }
+                       time[j+1] = v;
+               }
+               if (n > 1 && (n % 2) == 0)
+                       median = (time[n/2] + time[(n/2) + 1]) / 2
+               else
+                       median = time[(n+1)/2]
+
+               print $1, median
+       }
+}
diff --git a/traceroute.tproj/traceroute.8 b/traceroute.tproj/traceroute.8
new file mode 100644 (file)
index 0000000..5a1ca4c
--- /dev/null
@@ -0,0 +1,337 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Van Jacobson.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)traceroute.8       8.2 (Berkeley) 6/1/94
+.\"
+.Dd June 1, 1994
+.Dt TRACEROUTE 8
+.Os BSD 4.3
+.Sh NAME
+.Nm traceroute
+.Nd print the route packets take to network host
+.Sh SYNOPSIS
+.Nm traceroute
+.Op Fl m Ar max_ttl
+.Op Fl n
+.Op Fl p Ar port
+.Op Fl q Ar nqueries
+.Op Fl r
+.Bk -words
+.Op Fl s Ar src_addr
+.Ek
+.Op Fl t Ar tos
+.Op Fl w Ar waittime
+.Ar host
+.Op Ar packetsize
+.Sh DESCRIPTION
+The Internet is a large and complex aggregation of
+network hardware, connected together by gateways.
+Tracking the route one's packets follow (or finding the miscreant
+gateway that's discarding your packets) can be difficult.
+.Nm Traceroute
+utilizes the IP protocol `time to live' field and attempts to elicit an
+.Tn ICMP
+.Dv TIME_EXCEEDED
+response from each gateway along the path to some
+host.
+.Pp
+The only mandatory parameter is the destination host name or IP number.
+The default probe datagram length is 38 bytes, but this may be increased
+by specifying a packet size (in bytes) after the destination host
+name.
+.Pp
+Other options are:
+.Bl -tag -width Ds
+.It Fl m Ar max_ttl
+Set the max time-to-live (max number of hops) used in outgoing probe
+packets.  The default is 30 hops (the same default used for
+.Tn TCP
+connections).
+.It Fl n
+Print hop addresses numerically rather than symbolically and numerically
+(saves a nameserver address-to-name lookup for each gateway found on the
+path).
+.It Fl p Ar port
+Set the base
+.Tn UDP
+.Ar port
+number used in probes (default is 33434).
+.Nm Traceroute
+hopes that nothing is listening on
+.Tn UDP
+ports
+.Em base
+to
+.Em base+nhops-1
+at the destination host (so an
+.Tn ICMP
+.Dv PORT_UNREACHABLE
+message will
+be returned to terminate the route tracing).  If something is
+listening on a port in the default range, this option can be used
+to pick an unused port range.
+.It Fl q Ar nqueries
+Set the number of probes per ``ttl'' to
+.Ar nqueries
+(default is three probes).
+.It Fl r
+Bypass the normal routing tables and send directly to a host on an attached
+network.
+If the host is not on a directly-attached network,
+an error is returned.
+This option can be used to ping a local host through an interface
+that has no route through it (e.g., after the interface was dropped by
+.Xr routed 8 ) .
+.It Fl s Ar src_addr
+Use the following IP address
+(which must be given as an IP number, not
+a hostname) as the source address in outgoing probe packets.  On
+hosts with more than one IP address, this option can be used to
+force the source address to be something other than the IP address
+of the interface the probe packet is sent on.  If the IP address
+is not one of this machine's interface addresses, an error is
+returned and nothing is sent.
+.ne 1i
+.It Fl t Ar tos
+Set the
+.Em type-of-service
+in probe packets to the following value (default zero).  The value must be
+a decimal integer in the range 0 to 255.  This option can be used to
+see if different types-of-service result in different paths.  (If you
+are not running a
+.Bx 4.3 tahoe
+or later system, this may be academic since the normal network
+services like telnet and ftp don't let you control the
+.Dv TOS ) .
+Not all values of
+.Dv TOS
+are legal or
+meaningful \- see the IP spec for definitions.  Useful values are
+probably
+.Ql \-t 16
+(low delay) and
+.Ql \-t 8
+(high throughput).
+.It Fl v
+Verbose output.  Received
+.Tn ICMP
+packets other than
+.Dv TIME_EXCEEDED
+and
+.Dv UNREACHABLE Ns s
+are listed.
+.It Fl w
+Set the time (in seconds) to wait for a response to a probe (default 3
+sec.).
+.El
+.Pp
+This program attempts to trace the route an IP packet would follow to some
+internet host by launching
+.Tn UDP
+probe
+packets with a small ttl (time to live) then listening for an
+.Tn ICMP
+"time exceeded" reply from a gateway.  We start our probes
+with a ttl of one and increase by one until we get an
+.Tn ICMP
+"port unreachable"
+(which means we got to "host") or hit a max (which
+defaults to 30 hops & can be changed with the
+.Fl m
+flag).  Three
+probes (changed with
+.Fl q
+flag) are sent at each ttl setting and a
+line is printed showing the ttl, address of the gateway and
+round trip time of each probe.  If the probe answers come from
+different gateways, the address of each responding system will
+be printed.  If there is no response within a 3 sec. timeout
+interval (changed with the
+.Fl w
+flag), a "*" is printed for that
+probe.
+.Pp
+We don't want the destination
+host to process the
+.Tn UDP
+probe packets so the destination port is set to an
+unlikely value (if some clod on the destination is using that
+value, it can be changed with the
+.Fl p
+flag).
+.Pp
+A sample use and output might be:
+.Bd -literal
+[yak 71]% traceroute nis.nsf.net.
+traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
+1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
+2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
+3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
+4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
+5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
+6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
+7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
+8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
+9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
+10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
+11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
+
+.Ed
+Note that lines 2 & 3 are the same.  This is due to a buggy
+kernel on the 2nd hop system \- lbl-csam.arpa \- that forwards
+packets with a zero ttl (a bug in the distributed version
+of 4.3
+.Tn BSD ) .
+Note that you have to guess what path
+the packets are taking cross-country since the
+.Tn NSFNet
+(129.140)
+doesn't supply address-to-name translations for its
+.Tn NSS Ns es .
+.Pp
+A more interesting example is:
+.Bd -literal
+[yak 72]% traceroute allspice.lcs.mit.edu.
+traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
+1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
+2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
+3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
+4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
+5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
+6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
+7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
+8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
+9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
+10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
+11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
+12  * * *
+13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
+14  * * *
+15  * * *
+16  * * *
+17  * * *
+18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
+
+.Ed
+Note that the gateways 12, 14, 15, 16 & 17 hops away
+either don't send
+.Tn ICMP
+"time exceeded" messages or send them
+with a ttl too small to reach us.  14 \- 17 are running the
+.Tn MIT
+C Gateway code that doesn't send "time exceeded"s.  God
+only knows what's going on with 12.
+.Pp
+The silent gateway 12 in the above may be the result of a bug in
+the 4.[23]
+.Tn BSD
+network code (and its derivatives):  4.x (x <= 3)
+sends an unreachable message using whatever ttl remains in the
+original datagram.  Since, for gateways, the remaining ttl is
+zero, the
+.Tn ICMP
+"time exceeded" is guaranteed to not make it back
+to us.  The behavior of this bug is slightly more interesting
+when it appears on the destination system:
+.Bd -literal
+1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
+2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
+3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
+4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
+5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
+6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
+7  * * *
+8  * * *
+9  * * *
+10  * * *
+11  * * *
+12  * * *
+13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
+
+.Ed
+Notice that there are 12 "gateways" (13 is the final
+destination) and exactly the last half of them are "missing".
+What's really happening is that rip (a Sun-3 running Sun OS3.5)
+is using the ttl from our arriving datagram as the ttl in its
+.Tn ICMP
+reply.  So, the reply will time out on the return path
+(with no notice sent to anyone since
+.Tn ICMP's
+aren't sent for
+.Tn ICMP's )
+until we probe with a ttl that's at least twice the path
+length.  I.e., rip is really only 7 hops away.  A reply that
+returns with a ttl of 1 is a clue this problem exists.
+.Nm Traceroute
+prints a "!" after the time if the ttl is <= 1.
+Since vendors ship a lot of obsolete
+.Pf ( Tn DEC Ns \'s
+Ultrix, Sun 3.x) or
+non-standard
+.Pq Tn HPUX
+software, expect to see this problem
+frequently and/or take care picking the target host of your
+probes.
+Other possible annotations after the time are
+.Sy !H ,
+.Sy !N ,
+.Sy !P
+(got a host, network or protocol unreachable, respectively),
+.Sy !S
+or
+.Sy !F
+(source route failed or fragmentation needed \- neither of these should
+ever occur and the associated gateway is busted if you see one).  If
+almost all the probes result in some kind of unreachable,
+.Nm traceroute
+will give up and exit.
+.Pp
+This program is intended for use in network testing, measurement
+and management.
+It should be used primarily for manual fault isolation.
+Because of the load it could impose on the network, it is unwise to use
+.Nm traceroute
+during normal operations or from automated scripts.
+.Sh AUTHOR
+Implemented by Van Jacobson from a suggestion by Steve Deering.  Debugged
+by a cast of thousands with particularly cogent suggestions or fixes from
+C. Philip Wood, Tim Seaver and Ken Adelman.
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr ping 8
+.Sh HISTORY
+The
+.Nm
+command
+.Bt
diff --git a/traceroute.tproj/traceroute.c b/traceroute.tproj/traceroute.c
new file mode 100644 (file)
index 0000000..1f8a5fa
--- /dev/null
@@ -0,0 +1,858 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)traceroute.c       8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * traceroute host  - trace the route ip packets follow going to "host".
+ *
+ * Attempt to trace the route an ip packet would follow to some
+ * internet host.  We find out intermediate hops by launching probe
+ * packets with a small ttl (time to live) then listening for an
+ * icmp "time exceeded" reply from a gateway.  We start our probes
+ * with a ttl of one and increase by one until we get an icmp "port
+ * unreachable" (which means we got to "host") or hit a max (which
+ * defaults to 30 hops & can be changed with the -m flag).  Three
+ * probes (change with -q flag) are sent at each ttl setting and a
+ * line is printed showing the ttl, address of the gateway and
+ * round trip time of each probe.  If the probe answers come from
+ * different gateways, the address of each responding system will
+ * be printed.  If there is no response within a 5 sec. timeout
+ * interval (changed with the -w flag), a "*" is printed for that
+ * probe.
+ *
+ * Probe packets are UDP format.  We don't want the destination
+ * host to process them so the destination port is set to an
+ * unlikely value (if some clod on the destination is using that
+ * value, it can be changed with the -p flag).
+ *
+ * A sample use might be:
+ *
+ *     [yak 71]% traceroute nis.nsf.net.
+ *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
+ *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
+ *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
+ *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
+ *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
+ *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
+ *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
+ *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
+ *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
+ *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
+ *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
+ *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
+ *
+ * Note that lines 2 & 3 are the same.  This is due to a buggy
+ * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
+ * packets with a zero ttl.
+ *
+ * A more interesting example is:
+ *
+ *     [yak 72]% traceroute allspice.lcs.mit.edu.
+ *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
+ *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
+ *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
+ *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
+ *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
+ *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
+ *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
+ *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
+ *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
+ *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
+ *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
+ *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
+ *     12  * * *
+ *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
+ *     14  * * *
+ *     15  * * *
+ *     16  * * *
+ *     17  * * *
+ *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
+ *
+ * (I start to see why I'm having so much trouble with mail to
+ * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
+ * either don't send ICMP "time exceeded" messages or send them
+ * with a ttl too small to reach us.  14 - 17 are running the
+ * MIT C Gateway code that doesn't send "time exceeded"s.  God
+ * only knows what's going on with 12.
+ *
+ * The silent gateway 12 in the above may be the result of a bug in
+ * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
+ * sends an unreachable message using whatever ttl remains in the
+ * original datagram.  Since, for gateways, the remaining ttl is
+ * zero, the icmp "time exceeded" is guaranteed to not make it back
+ * to us.  The behavior of this bug is slightly more interesting
+ * when it appears on the destination system:
+ *
+ *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
+ *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
+ *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
+ *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
+ *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
+ *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
+ *      7  * * *
+ *      8  * * *
+ *      9  * * *
+ *     10  * * *
+ *     11  * * *
+ *     12  * * *
+ *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
+ *
+ * Notice that there are 12 "gateways" (13 is the final
+ * destination) and exactly the last half of them are "missing".
+ * What's really happening is that rip (a Sun-3 running Sun OS3.5)
+ * is using the ttl from our arriving datagram as the ttl in its
+ * icmp reply.  So, the reply will time out on the return path
+ * (with no notice sent to anyone since icmp's aren't sent for
+ * icmp's) until we probe with a ttl that's at least twice the path
+ * length.  I.e., rip is really only 7 hops away.  A reply that
+ * returns with a ttl of 1 is a clue this problem exists.
+ * Traceroute prints a "!" after the time if the ttl is <= 1.
+ * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
+ * non-standard (HPUX) software, expect to see this problem
+ * frequently and/or take care picking the target host of your
+ * probes.
+ *
+ * Other possible annotations after the time are !H, !N, !P (got a host,
+ * network or protocol unreachable, respectively), !S or !F (source
+ * route failed or fragmentation needed -- neither of these should
+ * ever occur and the associated gateway is busted if you see one).  If
+ * almost all the probes result in some kind of unreachable, traceroute
+ * will give up and exit.
+ *
+ * Notes
+ * -----
+ * This program must be run by root or be setuid.  (I suggest that
+ * you *don't* make it setuid -- casual use could result in a lot
+ * of unnecessary traffic on our poor, congested nets.)
+ *
+ * This program requires a kernel mod that does not appear in any
+ * system available from Berkeley:  A raw ip socket using proto
+ * IPPROTO_RAW must interpret the data sent as an ip datagram (as
+ * opposed to data to be wrapped in a ip datagram).  See the README
+ * file that came with the source to this program for a description
+ * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
+ * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
+ * MODIFIED TO RUN THIS PROGRAM.
+ *
+ * The udp port usage may appear bizarre (well, ok, it is bizarre).
+ * The problem is that an icmp message only contains 8 bytes of
+ * data from the original datagram.  8 bytes is the size of a udp
+ * header so, if we want to associate replies with the original
+ * datagram, the necessary information must be encoded into the
+ * udp header (the ip id could be used but there's no way to
+ * interlock with the kernel's assignment of ip id's and, anyway,
+ * it would have taken a lot more kernel hacking to allow this
+ * code to set the ip id).  So, to allow two or more users to
+ * use traceroute simultaneously, we use this task's pid as the
+ * source port (the high bit is set to move the port number out
+ * of the "likely" range).  To keep track of which probe is being
+ * replied to (so times and/or hop counts don't get confused by a
+ * reply that was delayed in transit), we increment the destination
+ * port number before each probe.
+ *
+ * Don't use this as a coding example.  I was trying to find a
+ * routing problem and this code sort-of popped out after 48 hours
+ * without sleep.  I was amazed it ever compiled, much less ran.
+ *
+ * I stole the idea for this program from Steve Deering.  Since
+ * the first release, I've learned that had I attended the right
+ * IETF working group meetings, I also could have stolen it from Guy
+ * Almes or Matt Mathis.  I don't know (or care) who came up with
+ * the idea first.  I envy the originators' perspicacity and I'm
+ * glad they didn't keep the idea a secret.
+ *
+ * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
+ * enhancements to the original distribution.
+ *
+ * I've hacked up a round-trip-route version of this that works by
+ * sending a loose-source-routed udp datagram through the destination
+ * back to yourself.  Unfortunately, SO many gateways botch source
+ * routing, the thing is almost worthless.  Maybe one day...
+ *
+ *  -- Van Jacobson (van@helios.ee.lbl.gov)
+ *     Tue Dec 20 03:50:13 PST 1988
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define        MAXPACKET       65535   /* max ip packet size */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#ifndef FD_SET
+#define NFDBITS         (8*sizeof(fd_set))
+#define FD_SETSIZE      NFDBITS
+#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
+#endif
+
+#define Fprintf (void)fprintf
+#define Sprintf (void)sprintf
+#define Printf (void)printf
+
+/*
+ * format of a (udp) probe packet.
+ */
+struct opacket {
+       struct ip ip;
+       struct udphdr udp;
+       u_char seq;             /* sequence number of this packet */
+       u_char ttl;             /* ttl packet left with */
+       struct timeval tv;      /* time packet left */
+};
+
+u_char packet[512];            /* last inbound (icmp) packet */
+struct opacket *outpacket;     /* last output (udp) packet */
+
+int wait_for_reply __P((int, struct sockaddr_in *));
+void send_probe __P((int, int));
+double deltaT __P((struct timeval *, struct timeval *));
+int packet_ok __P((u_char *, int, struct sockaddr_in *, int));
+void print __P((u_char *, int, struct sockaddr_in *));
+void tvsub __P((struct timeval *, struct timeval *));
+char *inetname __P((struct in_addr));
+void usage __P(());
+
+int s;                         /* receive (icmp) socket file descriptor */
+int sndsock;                   /* send (udp) socket file descriptor */
+struct timezone tz;            /* leftover */
+
+struct sockaddr whereto;       /* Who to try to reach */
+int datalen;                   /* How much data */
+
+char *source = 0;
+char *hostname;
+
+int nprobes = 3;
+int max_ttl = 30;
+u_short ident;
+u_short port = 32768+666;      /* start udp dest port # for probe packets */
+int options;                   /* socket options */
+int verbose;
+int waittime = 5;              /* time to wait for response (in seconds) */
+int nflag;                     /* print addresses numerically */
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern char *optarg;
+       extern int optind;
+       struct hostent *hp;
+       struct protoent *pe;
+       struct sockaddr_in from, *to;
+       int ch, i, on, probe, seq, tos, ttl;
+
+       on = 1;
+       seq = tos = 0;
+       to = (struct sockaddr_in *)&whereto;
+       while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)
+               switch(ch) {
+               case 'd':
+                       options |= SO_DEBUG;
+                       break;
+               case 'm':
+                       max_ttl = atoi(optarg);
+                       if (max_ttl <= 1) {
+                               Fprintf(stderr,
+                                   "traceroute: max ttl must be >1.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'n':
+                       nflag++;
+                       break;
+               case 'p':
+                       port = atoi(optarg);
+                       if (port < 1) {
+                               Fprintf(stderr,
+                                   "traceroute: port must be >0.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'q':
+                       nprobes = atoi(optarg);
+                       if (nprobes < 1) {
+                               Fprintf(stderr,
+                                   "traceroute: nprobes must be >0.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'r':
+                       options |= SO_DONTROUTE;
+                       break;
+               case 's':
+                       /*
+                        * set the ip source address of the outbound
+                        * probe (e.g., on a multi-homed host).
+                        */
+                       source = optarg;
+                       break;
+               case 't':
+                       tos = atoi(optarg);
+                       if (tos < 0 || tos > 255) {
+                               Fprintf(stderr,
+                                   "traceroute: tos must be 0 to 255.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               case 'w':
+                       waittime = atoi(optarg);
+                       if (waittime <= 1) {
+                               Fprintf(stderr,
+                                   "traceroute: wait must be >1 sec.\n");
+                               exit(1);
+                       }
+                       break;
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1)
+               usage();
+
+       setlinebuf (stdout);
+
+       (void) bzero((char *)&whereto, sizeof(struct sockaddr));
+       to->sin_family = AF_INET;
+       to->sin_addr.s_addr = inet_addr(*argv);
+       if (to->sin_addr.s_addr != -1)
+               hostname = *argv;
+       else {
+               hp = gethostbyname(*argv);
+               if (hp) {
+                       to->sin_family = hp->h_addrtype;
+                       bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
+                       hostname = hp->h_name;
+               } else {
+                       (void)fprintf(stderr,
+                           "traceroute: unknown host %s\n", *argv);
+                       exit(1);
+               }
+       }
+       if (*++argv)
+               datalen = atoi(*argv);
+       if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) {
+               Fprintf(stderr,
+                   "traceroute: packet size must be 0 <= s < %ld.\n",
+                   MAXPACKET - sizeof(struct opacket));
+               exit(1);
+       }
+       datalen += sizeof(struct opacket);
+       outpacket = (struct opacket *)malloc((unsigned)datalen);
+       if (! outpacket) {
+               perror("traceroute: malloc");
+               exit(1);
+       }
+       (void) bzero((char *)outpacket, datalen);
+       outpacket->ip.ip_dst = to->sin_addr;
+       outpacket->ip.ip_tos = tos;
+       outpacket->ip.ip_v = IPVERSION;
+       outpacket->ip.ip_id = 0;
+
+       ident = (getpid() & 0xffff) | 0x8000;
+
+       if ((pe = getprotobyname("icmp")) == NULL) {
+               Fprintf(stderr, "icmp: unknown protocol\n");
+               exit(10);
+       }
+       if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
+               perror("traceroute: icmp socket");
+               exit(5);
+       }
+       if (options & SO_DEBUG)
+               (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
+                                 (char *)&on, sizeof(on));
+       if (options & SO_DONTROUTE)
+               (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
+                                 (char *)&on, sizeof(on));
+
+       if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
+               perror("traceroute: raw socket");
+               exit(5);
+       }
+#ifdef SO_SNDBUF
+       if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
+                      sizeof(datalen)) < 0) {
+               perror("traceroute: SO_SNDBUF");
+               exit(6);
+       }
+#endif SO_SNDBUF
+#ifdef IP_HDRINCL
+       if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
+                      sizeof(on)) < 0) {
+               perror("traceroute: IP_HDRINCL");
+               exit(6);
+       }
+#endif IP_HDRINCL
+       if (options & SO_DEBUG)
+               (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
+                                 (char *)&on, sizeof(on));
+       if (options & SO_DONTROUTE)
+               (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
+                                 (char *)&on, sizeof(on));
+
+       if (source) {
+               (void) bzero((char *)&from, sizeof(struct sockaddr));
+               from.sin_family = AF_INET;
+               from.sin_addr.s_addr = inet_addr(source);
+               if (from.sin_addr.s_addr == -1) {
+                       Printf("traceroute: unknown host %s\n", source);
+                       exit(1);
+               }
+               outpacket->ip.ip_src = from.sin_addr;
+#ifndef IP_HDRINCL
+               if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
+                       perror ("traceroute: bind:");
+                       exit (1);
+               }
+#endif IP_HDRINCL
+       }
+
+       Fprintf(stderr, "traceroute to %s (%s)", hostname,
+               inet_ntoa(to->sin_addr));
+       if (source)
+               Fprintf(stderr, " from %s", source);
+       Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
+       (void) fflush(stderr);
+
+       for (ttl = 1; ttl <= max_ttl; ++ttl) {
+               u_long lastaddr = 0;
+               int got_there = 0;
+               int unreachable = 0;
+
+               Printf("%2d ", ttl);
+               for (probe = 0; probe < nprobes; ++probe) {
+                       int cc;
+                       struct timeval t1, t2;
+                       struct timezone tz;
+                       struct ip *ip;
+
+                       (void) gettimeofday(&t1, &tz);
+                       send_probe(++seq, ttl);
+                       while (cc = wait_for_reply(s, &from)) {
+                               (void) gettimeofday(&t2, &tz);
+                               if ((i = packet_ok(packet, cc, &from, seq))) {
+                                       if (from.sin_addr.s_addr != lastaddr) {
+                                               print(packet, cc, &from);
+                                               lastaddr = from.sin_addr.s_addr;
+                                       }
+                                       Printf("  %g ms", deltaT(&t1, &t2));
+                                       switch(i - 1) {
+                                       case ICMP_UNREACH_PORT:
+#ifndef ARCHAIC
+                                               ip = (struct ip *)packet;
+                                               if (ip->ip_ttl <= 1)
+                                                       Printf(" !");
+#endif ARCHAIC
+                                               ++got_there;
+                                               break;
+                                       case ICMP_UNREACH_NET:
+                                               ++unreachable;
+                                               Printf(" !N");
+                                               break;
+                                       case ICMP_UNREACH_HOST:
+                                               ++unreachable;
+                                               Printf(" !H");
+                                               break;
+                                       case ICMP_UNREACH_PROTOCOL:
+                                               ++got_there;
+                                               Printf(" !P");
+                                               break;
+                                       case ICMP_UNREACH_NEEDFRAG:
+                                               ++unreachable;
+                                               Printf(" !F");
+                                               break;
+                                       case ICMP_UNREACH_SRCFAIL:
+                                               ++unreachable;
+                                               Printf(" !S");
+                                               break;
+                                       }
+                                       break;
+                               }
+                       }
+                       if (cc == 0)
+                               Printf(" *");
+                       (void) fflush(stdout);
+               }
+               putchar('\n');
+               if (got_there || unreachable >= nprobes-1)
+                       exit(0);
+       }
+}
+
+int
+wait_for_reply(sock, from)
+       int sock;
+       struct sockaddr_in *from;
+{
+       fd_set fds;
+       struct timeval wait;
+       int cc = 0;
+       int fromlen = sizeof (*from);
+
+       FD_ZERO(&fds);
+       FD_SET(sock, &fds);
+       wait.tv_sec = waittime; wait.tv_usec = 0;
+
+       if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
+               cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
+                           (struct sockaddr *)from, &fromlen);
+
+       return(cc);
+}
+
+
+void
+send_probe(seq, ttl)
+       int seq, ttl;
+{
+       struct opacket *op = outpacket;
+       struct ip *ip = &op->ip;
+       struct udphdr *up = &op->udp;
+       int i;
+
+       ip->ip_off = 0;
+       ip->ip_hl = sizeof(*ip) >> 2;
+       ip->ip_p = IPPROTO_UDP;
+       ip->ip_len = datalen;
+       ip->ip_ttl = ttl;
+       ip->ip_v = IPVERSION;
+       ip->ip_id = htons(ident+seq);
+
+       up->uh_sport = htons(ident);
+       up->uh_dport = htons(port+seq);
+       up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip)));
+       up->uh_sum = 0;
+
+       op->seq = seq;
+       op->ttl = ttl;
+       (void) gettimeofday(&op->tv, &tz);
+
+       i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
+                  sizeof(struct sockaddr));
+       if (i < 0 || i != datalen)  {
+               if (i<0)
+                       perror("sendto");
+               Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
+                       datalen, i);
+               (void) fflush(stdout);
+       }
+}
+
+
+double
+deltaT(t1p, t2p)
+       struct timeval *t1p, *t2p;
+{
+       register double dt;
+
+       dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
+            (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
+       return (dt);
+}
+
+
+/*
+ * Convert an ICMP "type" field to a printable string.
+ */
+char *
+pr_type(t)
+       u_char t;
+{
+       static char *ttab[] = {
+       "Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
+       "Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
+       "Echo",         "ICMP 9",       "ICMP 10",      "Time Exceeded",
+       "Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",
+       "Info Reply"
+       };
+
+       if(t > 16)
+               return("OUT-OF-RANGE");
+
+       return(ttab[t]);
+}
+
+
+int
+packet_ok(buf, cc, from, seq)
+       u_char *buf;
+       int cc;
+       struct sockaddr_in *from;
+       int seq;
+{
+       register struct icmp *icp;
+       u_char type, code;
+       int hlen;
+#ifndef ARCHAIC
+       struct ip *ip;
+
+       ip = (struct ip *) buf;
+       hlen = ip->ip_hl << 2;
+       if (cc < hlen + ICMP_MINLEN) {
+               if (verbose)
+                       Printf("packet too short (%d bytes) from %s\n", cc,
+                               inet_ntoa(from->sin_addr));
+               return (0);
+       }
+       cc -= hlen;
+       icp = (struct icmp *)(buf + hlen);
+#else
+       icp = (struct icmp *)buf;
+#endif ARCHAIC
+       type = icp->icmp_type; code = icp->icmp_code;
+       if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
+           type == ICMP_UNREACH) {
+               struct ip *hip;
+               struct udphdr *up;
+
+               hip = &icp->icmp_ip;
+               hlen = hip->ip_hl << 2;
+               up = (struct udphdr *)((u_char *)hip + hlen);
+               if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
+                   up->uh_sport == htons(ident) &&
+                   up->uh_dport == htons(port+seq))
+                       return (type == ICMP_TIMXCEED? -1 : code+1);
+       }
+#ifndef ARCHAIC
+       if (verbose) {
+               int i;
+               u_long *lp = (u_long *)&icp->icmp_ip;
+
+               Printf("\n%d bytes from %s to %s", cc,
+                       inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
+               Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
+                      icp->icmp_code);
+               for (i = 4; i < cc ; i += sizeof(long))
+                       Printf("%2d: x%8.8lx\n", i, *lp++);
+       }
+#endif ARCHAIC
+       return(0);
+}
+
+
+void
+print(buf, cc, from)
+       u_char *buf;
+       int cc;
+       struct sockaddr_in *from;
+{
+       struct ip *ip;
+       int hlen;
+
+       ip = (struct ip *) buf;
+       hlen = ip->ip_hl << 2;
+       cc -= hlen;
+
+       if (nflag)
+               Printf(" %s", inet_ntoa(from->sin_addr));
+       else
+               Printf(" %s (%s)", inetname(from->sin_addr),
+                      inet_ntoa(from->sin_addr));
+
+       if (verbose)
+               Printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
+}
+
+
+#ifdef notyet
+/*
+ * Checksum routine for Internet Protocol family headers (C Version)
+ */
+u_short
+in_cksum(addr, len)
+       u_short *addr;
+       int len;
+{
+       register int nleft = len;
+       register u_short *w = addr;
+       register u_short answer;
+       register int sum = 0;
+
+       /*
+        *  Our algorithm is simple, using a 32 bit accumulator (sum),
+        *  we add sequential 16 bit words to it, and at the end, fold
+        *  back all the carry bits from the top 16 bits into the lower
+        *  16 bits.
+        */
+       while (nleft > 1)  {
+               sum += *w++;
+               nleft -= 2;
+       }
+
+       /* mop up an odd byte, if necessary */
+       if (nleft == 1)
+               sum += *(u_char *)w;
+
+       /*
+        * add back carry outs from top 16 bits to low 16 bits
+        */
+       sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
+       sum += (sum >> 16);                     /* add carry */
+       answer = ~sum;                          /* truncate to 16 bits */
+       return (answer);
+}
+#endif notyet
+
+/*
+ * Subtract 2 timeval structs:  out = out - in.
+ * Out is assumed to be >= in.
+ */
+void
+tvsub(out, in)
+       register struct timeval *out, *in;
+{
+       if ((out->tv_usec -= in->tv_usec) < 0)   {
+               out->tv_sec--;
+               out->tv_usec += 1000000;
+       }
+       out->tv_sec -= in->tv_sec;
+}
+
+
+/*
+ * Construct an Internet address representation.
+ * If the nflag has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+char *
+inetname(in)
+       struct in_addr in;
+{
+       register char *cp;
+       static char line[50];
+       struct hostent *hp;
+       static char domain[MAXHOSTNAMELEN + 1];
+       static int first = 1;
+
+       if (first && !nflag) {
+               first = 0;
+               if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+                   (cp = index(domain, '.')))
+                       (void) strcpy(domain, cp + 1);
+               else
+                       domain[0] = 0;
+       }
+       cp = 0;
+       if (!nflag && in.s_addr != INADDR_ANY) {
+               hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
+               if (hp) {
+                       if ((cp = index(hp->h_name, '.')) &&
+                           !strcmp(cp + 1, domain))
+                               *cp = 0;
+                       cp = hp->h_name;
+               }
+       }
+       if (cp)
+               (void) strcpy(line, cp);
+       else {
+               in.s_addr = ntohl(in.s_addr);
+#define C(x)   ((x) & 0xff)
+               Sprintf(line, "%lu.%lu.%lu.%lu", C(in.s_addr >> 24),
+                       C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
+       }
+       return (line);
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr,
+"usage: traceroute [-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\t\
+[-s src_addr] [-t tos] [-w wait] host [data size]\n");
+       exit(1);
+}
diff --git a/trpt.tproj/Makefile b/trpt.tproj/Makefile
new file mode 100644 (file)
index 0000000..3a0f3a7
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = trpt
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = trpt.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble trpt.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/trpt.tproj/Makefile.postamble b/trpt.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..a38e0df
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+INSTALL_AS_GROUP = kmem      # Group to chgrp app to 
+INSTALL_PERMISSIONS = 2555        # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
diff --git a/trpt.tproj/Makefile.preamble b/trpt.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2c9003c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/trpt.tproj/PB.project b/trpt.tproj/PB.project
new file mode 100644 (file)
index 0000000..e382ae0
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (trpt.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, trpt.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = trpt; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/trpt.tproj/trpt.8 b/trpt.tproj/trpt.8
new file mode 100644 (file)
index 0000000..8cc6c2a
--- /dev/null
@@ -0,0 +1,151 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)trpt.8     8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt TRPT 8
+.Os BSD 4.2
+.Sh NAME
+.Nm trpt
+.Nd transliterate protocol trace
+.Sh SYNOPSIS
+.Nm trpt
+.Op Fl a
+.Op Fl f
+.Op Fl j
+.Op Fl p Ar hex-address
+.Op Fl s
+.Op Fl t
+.Oo
+.Ar system Op Ar core
+.Oc
+.Sh DESCRIPTION
+.Nm Trpt
+interrogates the buffer of
+.Tn TCP
+trace records created
+when a socket is marked for
+.Dq debugging
+(see
+.Xr setsockopt 2 ) ,
+and prints a readable description of these records.
+When no options are supplied, 
+.Nm trpt
+prints all the trace records found in the system
+grouped according to
+.Tn TCP
+connection protocol control
+block
+.Pq Tn PCB .
+The following options may be used to
+alter this behavior.
+.Bl -tag -width Ds
+.It Fl a
+In addition to the normal output,
+print the values of the source and destination
+addresses for each packet recorded.
+.It Fl f
+Follow the trace as it occurs, waiting a short time for additional records
+each time the end of the log is reached.
+.It Fl j
+Just give a list of the protocol control block
+addresses for which there are trace records.
+.It Fl p
+Show only trace records associated with the protocol
+control block at the given address
+.Ar hex-address .
+.It Fl s
+In addition to the normal output,
+print a detailed description of the packet
+sequencing information.
+.It Fl t
+in addition to the normal output,
+print the values for all timers at each
+point in the trace.
+.El
+.Pp
+The recommended use of
+.Nm trpt
+is as follows.
+Isolate the problem and enable debugging on the
+socket(s) involved in the connection.
+Find the address of the protocol control blocks
+associated with the sockets using the 
+.Fl A
+option to 
+.Xr netstat 1 .
+Then run
+.Nm trpt
+with the
+.Fl p
+option, supplying the associated
+protocol control block addresses.
+The
+.Fl f
+option can be used to follow the trace log once the trace is located.
+If there are
+many sockets using the debugging option, the
+.Fl j
+option may be useful in checking to see if
+any trace records are present for the socket in
+question.
+.Pp
+If debugging is being performed on a system or
+core file other than the default, the last two
+arguments may be used to supplant the defaults.
+.Sh FILES
+.Bl -tag -width /dev/kmem -compact
+.It Pa /vmunix
+.It Pa /dev/kmem
+.El
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr setsockopt 2 ,
+.Xr trsp 8
+.Sh DIAGNOSTICS
+.Bl -tag -width Ds
+.It Sy no namelist
+When the system image doesn't
+contain the proper symbols to find the trace buffer;
+others which should be self explanatory.
+.El
+.Sh BUGS
+Should also print the data for each input or output,
+but this is not saved in the race record.
+.Pp
+The output format is inscrutable and should be described
+here.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/trpt.tproj/trpt.c b/trpt.tproj/trpt.c
new file mode 100644 (file)
index 0000000..63ad900
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)trpt.c     8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#if BSD >= 199103
+#define NEWVM
+#endif
+#ifndef NEWVM
+#include <machine/pte.h>
+#include <sys/vmmac.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#define PRUREQUESTS
+#include <sys/protosw.h>
+#include <sys/file.h>
+
+#include <net/route.h>
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#define        TCPTIMERS
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#define        TANAMES
+#include <netinet/tcp_debug.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <nlist.h>
+#include <paths.h>
+
+struct tcp_debug tcp_debug[TCP_NDEBUG];
+int    tcp_debx;
+
+struct nlist nl[] = {
+#define        N_TCP_DEBUG     0
+       { "_tcp_debug" },
+#define        N_TCP_DEBX      1
+       { "_tcp_debx" },
+#ifndef NEWVM
+#define        N_SYSMAP        2
+       { "_Sysmap" },
+#define        N_SYSSIZE       3
+       { "_Syssize" },
+#endif
+       { "" },
+};
+
+#ifndef NEWVM
+static struct pte *Sysmap;
+#endif
+static caddr_t tcp_pcbs[TCP_NDEBUG];
+static n_time ntime;
+static int aflag, kflag, memf, follow, sflag, tflag;
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern char *optarg;
+       extern int optind;
+       int ch, i, jflag, npcbs, numeric();
+       char *system, *core, *malloc();
+       off_t lseek();
+
+       jflag = npcbs = 0;
+       while ((ch = getopt(argc, argv, "afjp:st")) != EOF)
+               switch (ch) {
+               case 'a':
+                       ++aflag;
+                       break;
+               case 'f':
+                       ++follow;
+                       setlinebuf(stdout);
+                       break;
+               case 'j':
+                       ++jflag;
+                       break;
+               case 'p':
+                       if (npcbs >= TCP_NDEBUG) {
+                               fputs("trpt: too many pcb's specified\n",
+                                   stderr);
+                               exit(1);
+                       }
+                       (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]);
+                       break;
+               case 's':
+                       ++sflag;
+                       break;
+               case 't':
+                       ++tflag;
+                       break;
+               case '?':
+               default:
+                       (void)fprintf(stderr,
+"usage: trpt [-afjst] [-p hex-address] [system [core]]\n");
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+
+       core = _PATH_KMEM;
+       if (argc > 0) {
+               system = *argv;
+               argc--, argv++;
+               if (argc > 0) {
+                       core = *argv;
+                       argc--, argv++;
+                       ++kflag;
+               }
+               /*
+                * Discard setgid privileges if not the running kernel so that
+                * bad guys can't print interesting stuff from kernel memory.
+                */
+               setgid(getgid());
+       }
+       else
+               system = _PATH_UNIX;
+
+       if (nlist(system, nl) < 0 || !nl[0].n_value) {
+               fprintf(stderr, "trpt: %s: no namelist\n", system);
+               exit(1);
+       }
+       if ((memf = open(core, O_RDONLY)) < 0) {
+               perror(core);
+               exit(2);
+       }
+       if (kflag) {
+#ifdef NEWVM
+               fputs("trpt: can't do core files yet\n", stderr);
+               exit(1);
+#else
+               off_t off;
+
+               Sysmap = (struct pte *)
+                  malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
+               if (!Sysmap) {
+                       fputs("trpt: can't get memory for Sysmap.\n", stderr);
+                       exit(1);
+               }
+               off = nl[N_SYSMAP].n_value & ~KERNBASE;
+               (void)lseek(memf, off, L_SET);
+               (void)read(memf, (char *)Sysmap,
+                   (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
+#endif
+       }
+       (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
+       if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
+           sizeof(tcp_debx)) {
+               perror("trpt: tcp_debx");
+               exit(3);
+       }
+       (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
+       if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
+           sizeof(tcp_debug)) {
+               perror("trpt: tcp_debug");
+               exit(3);
+       }
+       /*
+        * If no control blocks have been specified, figure
+        * out how many distinct one we have and summarize
+        * them in tcp_pcbs for sorting the trace records
+        * below.
+        */
+       if (!npcbs) {
+               for (i = 0; i < TCP_NDEBUG; i++) {
+                       register struct tcp_debug *td = &tcp_debug[i];
+                       register int j;
+
+                       if (td->td_tcb == 0)
+                               continue;
+                       for (j = 0; j < npcbs; j++)
+                               if (tcp_pcbs[j] == td->td_tcb)
+                                       break;
+                       if (j >= npcbs)
+                               tcp_pcbs[npcbs++] = td->td_tcb;
+               }
+               if (!npcbs)
+                       exit(0);
+       }
+       qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric);
+       if (jflag) {
+               for (i = 0;;) {
+                       printf("%x", (int)tcp_pcbs[i]);
+                       if (++i == npcbs)
+                               break;
+                       fputs(", ", stdout);
+               }
+               putchar('\n');
+       }
+       else for (i = 0; i < npcbs; i++) {
+               printf("\n%x:\n", (int)tcp_pcbs[i]);
+               dotrace(tcp_pcbs[i]);
+       }
+       exit(0);
+}
+
+dotrace(tcpcb)
+       register caddr_t tcpcb;
+{
+       register struct tcp_debug *td;
+       register int i;
+       int prev_debx = tcp_debx;
+
+again: if (--tcp_debx < 0)
+               tcp_debx = TCP_NDEBUG - 1;
+       for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
+               td = &tcp_debug[i];
+               if (tcpcb && td->td_tcb != tcpcb)
+                       continue;
+               ntime = ntohl(td->td_time);
+               tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
+                   &td->td_th, td->td_req);
+               if (i == tcp_debx)
+                       goto done;
+       }
+       for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) {
+               td = &tcp_debug[i];
+               if (tcpcb && td->td_tcb != tcpcb)
+                       continue;
+               ntime = ntohl(td->td_time);
+               tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
+                   &td->td_th, td->td_req);
+       }
+done:  if (follow) {
+               prev_debx = tcp_debx + 1;
+               if (prev_debx >= TCP_NDEBUG)
+                       prev_debx = 0;
+               do {
+                       sleep(1);
+                       (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
+                       if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
+                           sizeof(tcp_debx)) {
+                               perror("trpt: tcp_debx");
+                               exit(3);
+                       }
+               } while (tcp_debx == prev_debx);
+               (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
+               if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
+                   sizeof(tcp_debug)) {
+                       perror("trpt: tcp_debug");
+                       exit(3);
+               }
+               goto again;
+       }
+}
+
+/*
+ * Tcp debug routines
+ */
+/*ARGSUSED*/
+tcp_trace(act, ostate, atp, tp, ti, req)
+       short act, ostate;
+       struct tcpcb *atp, *tp;
+       struct tcpiphdr *ti;
+       int req;
+{
+       tcp_seq seq, ack;
+       int flags, len, win, timer;
+
+       printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate],
+           tanames[act]);
+       switch (act) {
+       case TA_INPUT:
+       case TA_OUTPUT:
+       case TA_DROP:
+               if (aflag) {
+                       printf("(src=%s,%u, ",
+                           inet_ntoa(ti->ti_src), ntohs(ti->ti_sport));
+                       printf("dst=%s,%u)",
+                           inet_ntoa(ti->ti_dst), ntohs(ti->ti_dport));
+               }
+               seq = ti->ti_seq;
+               ack = ti->ti_ack;
+               len = ti->ti_len;
+               win = ti->ti_win;
+               if (act == TA_OUTPUT) {
+                       seq = ntohl(seq);
+                       ack = ntohl(ack);
+                       len = ntohs(len);
+                       win = ntohs(win);
+               }
+               if (act == TA_OUTPUT)
+                       len -= sizeof(struct tcphdr);
+               if (len)
+                       printf("[%lx..%lx)", seq, seq + len);
+               else
+                       printf("%lx", seq);
+               printf("@%lx", ack);
+               if (win)
+                       printf("(win=%x)", win);
+               flags = ti->ti_flags;
+               if (flags) {
+                       register char *cp = "<";
+#define        pf(flag, string) { \
+       if (ti->ti_flags&flag) { \
+               (void)printf("%s%s", cp, string); \
+               cp = ","; \
+       } \
+}
+                       pf(TH_SYN, "SYN");
+                       pf(TH_ACK, "ACK");
+                       pf(TH_FIN, "FIN");
+                       pf(TH_RST, "RST");
+                       pf(TH_PUSH, "PUSH");
+                       pf(TH_URG, "URG");
+                       printf(">");
+               }
+               break;
+       case TA_USER:
+               timer = req >> 8;
+               req &= 0xff;
+               printf("%s", prurequests[req]);
+               if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
+                       printf("<%s>", tcptimers[timer]);
+               break;
+       }
+       printf(" -> %s", tcpstates[tp->t_state]);
+       /* print out internal state of tp !?! */
+       printf("\n");
+       if (sflag) {
+               printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n",
+                   tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
+                   tp->snd_max);
+               printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1,
+                   tp->snd_wl2, tp->snd_wnd);
+       }
+       /* print out timers? */
+       if (tflag) {
+               register char *cp = "\t";
+               register int i;
+
+               for (i = 0; i < TCPT_NTIMERS; i++) {
+                       if (tp->t_timer[i] == 0)
+                               continue;
+                       printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
+                       if (i == TCPT_REXMT)
+                               printf(" (t_rxtshft=%d)", tp->t_rxtshift);
+                       cp = ", ";
+               }
+               if (*cp != '\t')
+                       putchar('\n');
+       }
+}
+
+numeric(c1, c2)
+       caddr_t *c1, *c2;
+{
+       return(*c1 - *c2);
+}
+
+klseek(fd, base, off)
+       int fd, off;
+       off_t base;
+{
+       off_t lseek();
+
+#ifndef NEWVM
+       if (kflag) {    /* get kernel pte */
+               base &= ~KERNBASE;
+               base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
+       }
+#endif
+       (void)lseek(fd, base, off);
+}
diff --git a/trsp.tproj/Makefile b/trsp.tproj/Makefile
new file mode 100644 (file)
index 0000000..4291787
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = trsp
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = trsp.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble trsp.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/trsp.tproj/Makefile.postamble b/trsp.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..a38e0df
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+INSTALL_AS_GROUP = kmem      # Group to chgrp app to 
+INSTALL_PERMISSIONS = 2555        # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# Makefile API), which are rules that get invoked before and after the install 
+# target runs.  Such rules should be specified with the '::' syntax rather than 
+# a single colon.
diff --git a/trsp.tproj/Makefile.preamble b/trsp.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2c9003c
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# To include a version string, project source must exist in a directory named
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/trsp.tproj/PB.project b/trsp.tproj/PB.project
new file mode 100644 (file)
index 0000000..26e29e4
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (trsp.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, trsp.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = trsp; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/trsp.tproj/trsp.8 b/trsp.tproj/trsp.8
new file mode 100644 (file)
index 0000000..19c23b4
--- /dev/null
@@ -0,0 +1,141 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)trsp.8     8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt TRSP 8
+.Os BSD 4.2
+.Sh NAME
+.Nm trsp
+.Nd transliterate sequenced packet protocol trace
+.Sh SYNOPSIS
+.Nm trsp
+.Op Fl a
+.Op Fl s
+.Op Fl t
+.Op Fl j
+.Op Fl p Ar hex-address
+.Oo
+.Ar system Op Ar core
+.Oc
+.Sh DESCRIPTION
+.Xr Trpt
+interrogates the buffer of
+.Tn SPP
+trace records created
+when a socket is marked for
+.Dq debugging
+(see
+.Xr setsockopt 2 ) ,
+and prints a readable description of these records.
+When no options are supplied, 
+.Nm trsp
+prints all the trace records found in the system
+grouped according to
+.Tn SPP
+connection protocol control
+block
+.Pq Tn PCB .
+The following options may be used to
+alter this behavior.
+.Bl -tag -width Ds
+.It Fl a
+In addition to the normal output,
+print the values of the source and destination
+addresses for each packet recorded.
+.It Fl j
+Just give a list of the protocol control block
+addresses for which there are trace records.
+.It Fl p
+Show only trace records associated with the protocol
+control block at the given address,
+.Ar hex-address .
+.It Fl s
+in addition to the normal output,
+print a detailed description of the packet
+sequencing information.
+.It Fl t
+in addition to the normal output,
+print the values for all timers at each
+point in the trace,
+.El
+.Pp
+The recommended use of
+.Nm trsp
+is as follows.
+Isolate the problem and enable debugging on the
+socket(s) involved in the connection.
+Find the address of the protocol control blocks
+associated with the sockets using the 
+.Fl A
+option to 
+.Xr netstat 1 .
+Then run
+.Nm trsp
+with the
+.Fl p
+option, supplying the associated
+protocol control block addresses.  If there are
+many sockets using the debugging option, the
+.Fl j
+option may be useful in checking to see if
+any trace records are present for the socket in
+question.
+.Pp
+If debugging is being performed on a system or
+core file other than the default, the last two
+arguments may be used to supplant the defaults.
+.Sh FILES
+.Bl -tag -width /dev/kmem -compact
+.It Pa /vmunix
+.It Pa /dev/kmem
+.El
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr setsockopt 2
+.Sh DIAGNOSTICS
+.Bl -tag -width Ds
+.It Sy no namelist
+When the system image doesn't
+contain the proper symbols to find the trace buffer;
+others which should be self explanatory.
+.Sh BUGS
+Should also print the data for each input or output,
+but this is not saved in the race record.
+.Pp
+The output format is inscrutable and should be described
+here.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/trsp.tproj/trsp.c b/trsp.tproj/trsp.c
new file mode 100644 (file)
index 0000000..6895ff9
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)trsp.c     8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#define PRUREQUESTS
+#include <sys/protosw.h>
+
+#include <net/route.h>
+#include <net/if.h>
+
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#define        TCPTIMERS
+#include <netinet/tcp_timer.h>
+
+#include <netns/ns.h>
+#include <netns/sp.h>
+#include <netns/idp.h>
+#include <netns/spidp.h>
+#include <netns/spp_timer.h>
+#include <netns/spp_var.h>
+#include <netns/ns_pcb.h>
+#include <netns/idp_var.h>
+#define SANAMES
+#include <netns/spp_debug.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <nlist.h>
+#include <paths.h>
+
+unsigned long  ntime;
+int    sflag;
+int    tflag;
+int    jflag;
+int    aflag;
+int    zflag;
+int    numeric();
+struct nlist nl[] = {
+       { "_spp_debug" },
+       { "_spp_debx" },
+       0
+};
+struct spp_debug spp_debug[SPP_NDEBUG];
+caddr_t        spp_pcbs[SPP_NDEBUG];
+int    spp_debx;
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       int i, mask = 0, npcbs = 0;
+       char *system, *core;
+
+       system = _PATH_UNIX;
+       core = _PATH_KMEM;
+
+       argc--, argv++;
+again:
+       if (argc > 0 && !strcmp(*argv, "-a")) {
+               aflag++, argc--, argv++;
+               goto again;
+       }
+       if (argc > 0 && !strcmp(*argv, "-z")) {
+               zflag++, argc--, argv++;
+               goto again;
+       }
+       if (argc > 0 && !strcmp(*argv, "-s")) {
+               sflag++, argc--, argv++;
+               goto again;
+       }
+       if (argc > 0 && !strcmp(*argv, "-t")) {
+               tflag++, argc--, argv++;
+               goto again;
+       }
+       if (argc > 0 && !strcmp(*argv, "-j")) {
+               jflag++, argc--, argv++;
+               goto again;
+       }
+       if (argc > 0 && !strcmp(*argv, "-p")) {
+               argc--, argv++;
+               if (argc < 1) {
+                       fprintf(stderr, "-p: missing sppcb address\n");
+                       exit(1);
+               }
+               if (npcbs >= SPP_NDEBUG) {
+                       fprintf(stderr, "-p: too many pcb's specified\n");
+                       exit(1);
+               }
+               sscanf(*argv, "%x", &spp_pcbs[npcbs++]);
+               argc--, argv++;
+               goto again;
+       }
+       if (argc > 0) {
+               system = *argv;
+               argc--, argv++;
+               mask++;
+               /*
+                * Discard setgid privileges if not the running kernel so that
+                * bad guys can't print interesting stuff from kernel memory.
+                */
+               setgid(getgid());
+       }
+       if (argc > 0) {
+               core = *argv;
+               argc--, argv++;
+               mask++;
+               setgid(getgid());
+       }
+       (void) nlist(system, nl);
+       if (nl[0].n_value == 0) {
+               fprintf(stderr, "trsp: %s: no namelist\n", system);
+               exit(1);
+       }
+       (void) close(0);
+       if (open(core, 0) < 0) {
+               fprintf(stderr, "trsp: "); perror(core);
+               exit(2);
+       }
+       if (mask) {
+               nl[0].n_value &= 0x7fffffff;
+               nl[1].n_value &= 0x7fffffff;
+       }
+       (void) lseek(0, nl[1].n_value, 0);
+       if (read(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) {
+               fprintf(stderr, "trsp: "); perror("spp_debx");
+               exit(3);
+       }
+       printf("spp_debx=%d\n", spp_debx);
+       (void) lseek(0, nl[0].n_value, 0);
+       if (read(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) {
+               fprintf(stderr, "trsp: "); perror("spp_debug");
+               exit(3);
+       }
+       /*
+        * Here, we just want to clear out the old trace data and start over.
+        */
+       if (zflag) {
+               char *cp = (char *) spp_debug,
+                    *cplim = cp + sizeof(spp_debug);
+               (void) close(0);
+               if (open(core, 2) < 0) {
+                       fprintf(stderr, "trsp: "); perror(core);
+                       exit(2);
+               }
+               while(cp < cplim) *cp++ = 0;
+               (void) lseek(0, nl[0].n_value, 0);
+               if (write(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) {
+                       fprintf(stderr, "trsp: "); perror("spp_debug");
+                       exit(3);
+               }
+               (void) lseek(0, nl[1].n_value, 0);
+               spp_debx = 0;
+               if (write(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) {
+                       fprintf(stderr, "trsp: "); perror("spp_debx");
+                       exit(3);
+               }
+               exit(0);
+       }
+       /*
+        * If no control blocks have been specified, figure
+        * out how many distinct one we have and summarize
+        * them in spp_pcbs for sorting the trace records
+        * below.
+        */
+       if (npcbs == 0) {
+               for (i = 0; i < SPP_NDEBUG; i++) {
+                       register int j;
+                       register struct spp_debug *sd = &spp_debug[i];
+
+                       if (sd->sd_cb == 0)
+                               continue;
+                       for (j = 0; j < npcbs; j++)
+                               if (spp_pcbs[j] == sd->sd_cb)
+                                       break;
+                       if (j >= npcbs)
+                               spp_pcbs[npcbs++] = sd->sd_cb;
+               }
+       }
+       qsort(spp_pcbs, npcbs, sizeof (caddr_t), numeric);
+       if (jflag) {
+               char *cp = "";
+
+               for (i = 0; i < npcbs; i++) {
+                       printf("%s%x", cp, spp_pcbs[i]);
+                       cp = ", ";
+               }
+               if (*cp)
+                       putchar('\n');
+               exit(0);
+       }
+       for (i = 0; i < npcbs; i++) {
+               printf("\n%x:\n", spp_pcbs[i]);
+               dotrace(spp_pcbs[i]);
+       }
+       exit(0);
+}
+
+dotrace(sppcb)
+       register caddr_t sppcb;
+{
+       register int i;
+       register struct spp_debug *sd;
+
+       for (i = spp_debx % SPP_NDEBUG; i < SPP_NDEBUG; i++) {
+               sd = &spp_debug[i];
+               if (sppcb && sd->sd_cb != sppcb)
+                       continue;
+               ntime = ntohl(sd->sd_time);
+               spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp,
+                   &sd->sd_si, sd->sd_req);
+       }
+       for (i = 0; i < spp_debx % SPP_NDEBUG; i++) {
+               sd = &spp_debug[i];
+               if (sppcb && sd->sd_cb != sppcb)
+                       continue;
+               ntime = ntohl(sd->sd_time);
+               spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp,
+                   &sd->sd_si, sd->sd_req);
+       }
+}
+
+ptime(ms)
+       int ms;
+{
+
+       printf("%03d ", (ms/10) % 1000);
+}
+
+numeric(c1, c2)
+       caddr_t *c1, *c2;
+{
+       
+       return (*c1 - *c2);
+}
+
+spp_trace(act, ostate, asp, sp, si, req)
+       short act, ostate;
+       struct sppcb *asp, *sp;
+       struct spidp *si;
+       int req;
+{
+       u_short seq, ack, len, alo;
+       int flags, timer;
+       char *cp;
+
+       if(ostate >= TCP_NSTATES) ostate = 0;
+       if(act > SA_DROP) act = SA_DROP;
+       printf("\n");
+       ptime(ntime);
+       printf("%s:%s", tcpstates[ostate], sanames[act]);
+
+       if (si != 0) {
+               seq = si->si_seq;
+               ack = si->si_ack;
+               alo = si->si_alo;
+               len = si->si_len;
+               switch (act) {
+               case SA_RESPOND:
+               case SA_OUTPUT:
+                               seq = ntohs(seq);
+                               ack = ntohs(ack);
+                               alo = ntohs(alo);
+                               len = ntohs(len);
+               case SA_INPUT:
+               case SA_DROP:
+                       if (aflag) {
+                               printf("\n\tsna=");
+                               ns_printhost(&si->si_sna);
+                               printf("\tdna=");
+                               ns_printhost(&si->si_dna);
+                       }
+                       printf("\n\t");
+#define p1(name, f) { \
+       printf("%s = %x, ", name, f); \
+ }
+                       p1("seq", seq);
+                       p1("ack", ack);
+                       p1("alo", alo);
+                       p1("len", len);
+                       flags = si->si_cc;
+                       printf("flags=%x", flags);
+#define pf(name, f) { \
+       if (flags & f) { \
+               printf("%s%s", cp, name); \
+               cp = ","; \
+       } \
+}
+                       if (flags) {
+                               char *cp = "<";
+                               pf("SP_SP", SP_SP);
+                               pf("SP_SA", SP_SA);
+                               pf("SP_OB", SP_OB);
+                               pf("SP_EM", SP_EM);
+                               printf(">");
+                       }
+                       printf(", ");
+#define p2(name, f) { \
+       printf("%s = %x, ", name, f); \
+}
+                       p2("sid", si->si_sid);
+                       p2("did", si->si_did);
+                       p2("dt", si->si_dt);
+                       printf("\n\tsna=");
+                       ns_printhost(&si->si_sna);
+                       printf("\tdna=");
+                       ns_printhost(&si->si_dna);
+               }
+       }
+       if(act == SA_USER) {
+               printf("\treq=%s", prurequests[req&0xff]);
+               if ((req & 0xff) == PRU_SLOWTIMO)
+                       printf("<%s>", tcptimers[req>>8]);
+       }
+       printf(" -> %s", tcpstates[sp->s_state]);
+
+       /* print out internal state of sp !?! */
+       printf("\n");
+       if (sp == 0)
+               return;
+#define p3(name, f)  { \
+       printf("%s = %x, ", name, f); \
+}
+       if (sflag) {
+               printf("\t");
+               p3("rack", sp->s_rack);
+               p3("ralo", sp->s_ralo);
+               p3("smax", sp->s_smax);
+               p3("snxt", sp->s_snxt);
+               p3("flags", sp->s_flags);
+#undef pf
+#define pf(name, f) { \
+       if (flags & f) { \
+               printf("%s%s", cp, name); \
+               cp = ","; \
+       } \
+}
+               flags = sp->s_flags;
+               if (flags || sp->s_oobflags) {
+                       char *cp = "<";
+                       pf("ACKNOW", SF_ACKNOW);
+                       pf("DELACK", SF_DELACK);
+                       pf("HI", SF_HI);
+                       pf("HO", SF_HO);
+                       pf("PI", SF_PI);
+                       pf("WIN", SF_WIN);
+                       pf("RXT", SF_RXT);
+                       pf("RVD", SF_RVD);
+                       flags = sp->s_oobflags;
+                       pf("SOOB", SF_SOOB);
+                       pf("IOOB", SF_IOOB);
+                       printf(">");
+               }
+       }
+       /* print out timers? */
+       if (tflag) {
+               char *cp = "\t";
+               register int i;
+
+               printf("\n\tTIMERS: ");
+               p3("idle", sp->s_idle);
+               p3("force", sp->s_force);
+               p3("rtseq", sp->s_rtseq);
+               for (i = 0; i < TCPT_NTIMERS; i++) {
+                       if (sp->s_timer[i] == 0)
+                               continue;
+                       printf("%s%s=%d", cp, tcptimers[i], sp->s_timer[i]);
+                       if (i == TCPT_REXMT)
+                               printf(" (s_rxtshft=%d)", sp->s_rxtshift);
+                       cp = ", ";
+               }
+               if (*cp != '\t')
+                       putchar('\n');
+       }
+}
+
+ns_printhost(p)
+register struct ns_addr *p;
+{
+
+       printf("<net:%x%x,host:%4.4x%4.4x%4.4x,port:%x>",
+                       p->x_net.s_net[0],
+                       p->x_net.s_net[1],
+                       p->x_host.s_host[0],
+                       p->x_host.s_host[1],
+                       p->x_host.s_host[2],
+                       p->x_port);
+
+}
+
diff --git a/uucpd.tproj/Makefile b/uucpd.tproj/Makefile
new file mode 100644 (file)
index 0000000..4c25374
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = uucpd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = uucpd.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/uucpd.tproj/Makefile.postamble b/uucpd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7ede358
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
diff --git a/uucpd.tproj/Makefile.preamble b/uucpd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dcbd1c8
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
diff --git a/uucpd.tproj/PB.project b/uucpd.tproj/PB.project
new file mode 100644 (file)
index 0000000..ba6c171
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (uucpd.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = uucpd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/uucpd.tproj/pathnames.h b/uucpd.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..0383391
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ */
+
+#include <paths.h>
+
+#define        _PATH_UUCICO    "/usr/lib/uucp/uucico"
diff --git a/uucpd.tproj/uucpd.c b/uucpd.tproj/uucpd.c
new file mode 100644 (file)
index 0000000..4a5445c
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Adams.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)uucpd.c    8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * 4.2BSD TCP/IP server for uucico
+ * uucico's TCP channel causes this server to be run at the remote end.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <time.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pathnames.h"
+
+struct sockaddr_in hisctladdr;
+int hisaddrlen = sizeof hisctladdr;
+struct sockaddr_in myctladdr;
+int mypid;
+
+char Username[64];
+char *nenv[] = {
+       Username,
+       NULL,
+};
+extern char **environ;
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+#ifndef BSDINETD
+       register int s, tcp_socket;
+       struct servent *sp;
+#endif !BSDINETD
+       extern int errno;
+       int dologout();
+
+       environ = nenv;
+#ifdef BSDINETD
+       close(1); close(2);
+       dup(0); dup(0);
+       hisaddrlen = sizeof (hisctladdr);
+       if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
+               fprintf(stderr, "%s: ", argv[0]);
+               perror("getpeername");
+               _exit(1);
+       }
+       if (fork() == 0)
+               doit(&hisctladdr);
+       dologout();
+       exit(1);
+#else !BSDINETD
+       sp = getservbyname("uucp", "tcp");
+       if (sp == NULL){
+               perror("uucpd: getservbyname");
+               exit(1);
+       }
+       if (fork())
+               exit(0);
+       if ((s=open(_PATH_TTY, 2)) >= 0){
+               ioctl(s, TIOCNOTTY, (char *)0);
+               close(s);
+       }
+
+       bzero((char *)&myctladdr, sizeof (myctladdr));
+       myctladdr.sin_family = AF_INET;
+       myctladdr.sin_port = sp->s_port;
+#ifdef BSD4_2
+       tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
+       if (tcp_socket < 0) {
+               perror("uucpd: socket");
+               exit(1);
+       }
+       if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
+               perror("uucpd: bind");
+               exit(1);
+       }
+       listen(tcp_socket, 3);  /* at most 3 simultaneuos uucp connections */
+       signal(SIGCHLD, dologout);
+
+       for(;;) {
+               s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
+               if (s < 0){
+                       if (errno == EINTR) 
+                               continue;
+                       perror("uucpd: accept");
+                       exit(1);
+               }
+               if (fork() == 0) {
+                       close(0); close(1); close(2);
+                       dup(s); dup(s); dup(s);
+                       close(tcp_socket); close(s);
+                       doit(&hisctladdr);
+                       exit(1);
+               }
+               close(s);
+       }
+#endif BSD4_2
+
+#endif !BSDINETD
+}
+
+doit(sinp)
+struct sockaddr_in *sinp;
+{
+       char user[64], passwd[64];
+       char *xpasswd, *crypt();
+       struct passwd *pw, *getpwnam();
+
+       alarm(60);
+       printf("login: "); fflush(stdout);
+       if (readline(user, sizeof user) < 0) {
+               fprintf(stderr, "user read\n");
+               return;
+       }
+       /* truncate username to 8 characters */
+       user[8] = '\0';
+       pw = getpwnam(user);
+       if (pw == NULL) {
+               fprintf(stderr, "user unknown\n");
+               return;
+       }
+       if (strcmp(pw->pw_shell, _PATH_UUCICO)) {
+               fprintf(stderr, "Login incorrect.");
+               return;
+       }
+       if (pw->pw_passwd && *pw->pw_passwd != '\0') {
+               printf("Password: "); fflush(stdout);
+               if (readline(passwd, sizeof passwd) < 0) {
+                       fprintf(stderr, "passwd read\n");
+                       return;
+               }
+               xpasswd = crypt(passwd, pw->pw_passwd);
+               if (strcmp(xpasswd, pw->pw_passwd)) {
+                       fprintf(stderr, "Login incorrect.");
+                       return;
+               }
+       }
+       alarm(0);
+       sprintf(Username, "USER=%s", user);
+       dologin(pw, sinp);
+       setgid(pw->pw_gid);
+#ifdef BSD4_2
+       initgroups(pw->pw_name, pw->pw_gid);
+#endif BSD4_2
+       chdir(pw->pw_dir);
+       setuid(pw->pw_uid);
+#ifdef BSD4_2
+       execl(UUCICO, "uucico", (char *)0);
+#endif BSD4_2
+       perror("uucico server: execl");
+}
+
+readline(p, n)
+register char *p;
+register int n;
+{
+       char c;
+
+       while (n-- > 0) {
+               if (read(0, &c, 1) <= 0)
+                       return(-1);
+               c &= 0177;
+               if (c == '\n' || c == '\r') {
+                       *p = '\0';
+                       return(0);
+               }
+               *p++ = c;
+       }
+       return(-1);
+}
+
+#include <utmp.h>
+#ifdef BSD4_2
+#include <fcntl.h>
+#endif BSD4_2
+
+#define        SCPYN(a, b)     strncpy(a, b, sizeof (a))
+
+struct utmp utmp;
+
+dologout()
+{
+       union wait status;
+       int pid, wtmp;
+
+#ifdef BSDINETD
+       while ((pid=wait((int *)&status)) > 0) {
+#else  !BSDINETD
+       while ((pid=wait3((int *)&status,WNOHANG,0)) > 0) {
+#endif !BSDINETD
+               wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
+               if (wtmp >= 0) {
+                       sprintf(utmp.ut_line, "uucp%.4d", pid);
+                       SCPYN(utmp.ut_name, "");
+                       SCPYN(utmp.ut_host, "");
+                       (void) time(&utmp.ut_time);
+                       (void) write(wtmp, (char *)&utmp, sizeof (utmp));
+                       (void) close(wtmp);
+               }
+       }
+}
+
+/*
+ * Record login in wtmp file.
+ */
+dologin(pw, sin)
+struct passwd *pw;
+struct sockaddr_in *sin;
+{
+       char line[32];
+       char remotehost[32];
+       int wtmp, f;
+       struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr,
+               sizeof (struct in_addr), AF_INET);
+
+       if (hp) {
+               strncpy(remotehost, hp->h_name, sizeof (remotehost));
+               endhostent();
+       } else
+               strncpy(remotehost, inet_ntoa(sin->sin_addr),
+                   sizeof (remotehost));
+       wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
+       if (wtmp >= 0) {
+               /* hack, but must be unique and no tty line */
+               sprintf(line, "uucp%.4d", getpid());
+               SCPYN(utmp.ut_line, line);
+               SCPYN(utmp.ut_name, pw->pw_name);
+               SCPYN(utmp.ut_host, remotehost);
+               time(&utmp.ut_time);
+               (void) write(wtmp, (char *)&utmp, sizeof (utmp));
+               (void) close(wtmp);
+       }
+       if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
+               struct lastlog ll;
+
+               time(&ll.ll_time);
+               lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
+               strcpy(line, remotehost);
+               SCPYN(ll.ll_line, line);
+               SCPYN(ll.ll_host, remotehost);
+               (void) write(f, (char *) &ll, sizeof ll);
+               (void) close(f);
+       }
+}
diff --git a/wall.tproj/Makefile b/wall.tproj/Makefile
new file mode 100644 (file)
index 0000000..9d20c3c
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = wall
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ttymsg.c wall.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            wall.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/wall.tproj/Makefile.dist b/wall.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..65abb61
--- /dev/null
@@ -0,0 +1,8 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/6/93
+
+PROG=  wall
+SRCS=  ttymsg.c wall.c
+BINGRP=        tty
+BINMODE=2555
+
+.include <bsd.prog.mk>
diff --git a/wall.tproj/Makefile.postamble b/wall.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..851f5b0
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root
+        # User/group ownership 
+INSTALL_AS_GROUP = tty
+        # (probably want to set both of these) 
+INSTALL_PERMISSIONS = 2555
+        # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/wall.tproj/Makefile.preamble b/wall.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/wall.tproj/PB.project b/wall.tproj/PB.project
new file mode 100644 (file)
index 0000000..d0b5d25
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (ttymsg.c, wall.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, wall.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = wall; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/wall.tproj/ttymsg.c b/wall.tproj/ttymsg.c
new file mode 100644 (file)
index 0000000..45e4d2d
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <paths.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ * Display the contents of a uio structure on a terminal.  Used by wall(1),
+ * syslogd(8), and talkd(8).  Forks and finishes in child if write would block,
+ * waiting up to tmout seconds.  Returns pointer to error string on unexpected
+ * error; string is not newline-terminated.  Various "normal" errors are
+ * ignored (exclusive-use, lack of permission, etc.).
+ */
+char *
+ttymsg(iov, iovcnt, line, tmout)
+       struct iovec *iov;
+       int iovcnt;
+       char *line;
+       int tmout;
+{
+       static char device[MAXNAMLEN] = _PATH_DEV;
+       static char errbuf[1024];
+       register int cnt, fd, left, wret;
+       struct iovec localiov[6];
+       int forked = 0;
+
+       if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
+               return ("too many iov's (change code in wall/ttymsg.c)");
+
+       (void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
+       if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) {
+               /* A slash is an attempt to break security... */
+               (void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"",
+                   device);
+               return (errbuf);
+       }
+
+       /*
+        * open will fail on slip lines or exclusive-use lines
+        * if not running as root; not an error.
+        */
+       if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
+               if (errno == EBUSY || errno == EACCES)
+                       return (NULL);
+               (void) snprintf(errbuf, sizeof(errbuf),
+                   "%s: %s", device, strerror(errno));
+               return (errbuf);
+       }
+
+       for (cnt = left = 0; cnt < iovcnt; ++cnt)
+               left += iov[cnt].iov_len;
+
+       for (;;) {
+               wret = writev(fd, iov, iovcnt);
+               if (wret >= left)
+                       break;
+               if (wret >= 0) {
+                       left -= wret;
+                       if (iov != localiov) {
+                               bcopy(iov, localiov,
+                                   iovcnt * sizeof(struct iovec));
+                               iov = localiov;
+                       }
+                       for (cnt = 0; wret >= iov->iov_len; ++cnt) {
+                               wret -= iov->iov_len;
+                               ++iov;
+                               --iovcnt;
+                       }
+                       if (wret) {
+                               iov->iov_base += wret;
+                               iov->iov_len -= wret;
+                       }
+                       continue;
+               }
+               if (errno == EWOULDBLOCK) {
+                       int cpid, off = 0;
+
+                       if (forked) {
+                               (void) close(fd);
+                               _exit(1);
+                       }
+                       cpid = fork();
+                       if (cpid < 0) {
+                               (void) snprintf(errbuf, sizeof(errbuf),
+                                   "fork: %s", strerror(errno));
+                               (void) close(fd);
+                               return (errbuf);
+                       }
+                       if (cpid) {     /* parent */
+                               (void) close(fd);
+                               return (NULL);
+                       }
+                       forked++;
+                       /* wait at most tmout seconds */
+                       (void) signal(SIGALRM, SIG_DFL);
+                       (void) signal(SIGTERM, SIG_DFL); /* XXX */
+                       (void) sigsetmask(0);
+                       (void) alarm((u_int)tmout);
+                       (void) fcntl(fd, O_NONBLOCK, &off);
+                       continue;
+               }
+               /*
+                * We get ENODEV on a slip line if we're running as root,
+                * and EIO if the line just went away.
+                */
+               if (errno == ENODEV || errno == EIO)
+                       break;
+               (void) close(fd);
+               if (forked)
+                       _exit(1);
+               (void) snprintf(errbuf, sizeof(errbuf),
+                   "%s: %s", device, strerror(errno));
+               return (errbuf);
+       }
+
+       (void) close(fd);
+       if (forked)
+               _exit(0);
+       return (NULL);
+}
diff --git a/wall.tproj/wall.1 b/wall.tproj/wall.1
new file mode 100644 (file)
index 0000000..ed2f4c9
--- /dev/null
@@ -0,0 +1,63 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)wall.1     8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt WALL 1
+.Os BSD 4
+.Sh NAME
+.Nm wall
+.Nd write a message to users
+.Sh SYNOPSIS
+.Nm wall
+.Op Ar file
+.Sh DESCRIPTION
+.Nm Wall
+displays the contents of
+.Ar file
+or, by default, its standard input, on the terminals of all
+currently logged in users.
+.Pp
+Only the super-user can write on the
+terminals of users who have chosen
+to deny messages or are using a program which
+automatically denies messages.
+.Sh SEE ALSO
+.Xr mesg 1 ,
+.Xr talk 1 ,
+.Xr write 1 ,
+.Xr shutdown 8
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v7 .
diff --git a/wall.tproj/wall.c b/wall.tproj/wall.c
new file mode 100644 (file)
index 0000000..e08a8dd
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1988, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1990, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+/*
+ * This program is not related to David Wall, whose Stanford Ph.D. thesis
+ * is entitled "Mechanisms for Broadcast and Selective Broadcast".
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+
+void   makemsg __P((char *));
+
+#define        IGNOREUSER      "sleeper"
+
+int nobanner;
+int mbufsize;
+char *mbuf;
+
+/* ARGSUSED */
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern int optind;
+       int ch;
+       struct iovec iov;
+       struct utmp utmp;
+       FILE *fp;
+       char *p, *ttymsg();
+       char line[sizeof(utmp.ut_line) + 1];
+
+       while ((ch = getopt(argc, argv, "n")) != EOF)
+               switch (ch) {
+               case 'n':
+                       /* undoc option for shutdown: suppress banner */
+                       if (geteuid() == 0)
+                               nobanner = 1;
+                       break;
+               case '?':
+               default:
+usage:
+                       (void)fprintf(stderr, "usage: wall [file]\n");
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+       if (argc > 1)
+               goto usage;
+
+       makemsg(*argv);
+
+       if (!(fp = fopen(_PATH_UTMP, "r"))) {
+               (void)fprintf(stderr, "wall: cannot read %s.\n", _PATH_UTMP);
+               exit(1);
+       }
+       iov.iov_base = mbuf;
+       iov.iov_len = mbufsize;
+       /* NOSTRICT */
+       while (fread((char *)&utmp, sizeof(utmp), 1, fp) == 1) {
+               if (!utmp.ut_name[0] ||
+                   !strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name)))
+                       continue;
+               strncpy(line, utmp.ut_line, sizeof(utmp.ut_line));
+               line[sizeof(utmp.ut_line)] = '\0';
+               if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL)
+                       (void)fprintf(stderr, "wall: %s\n", p);
+       }
+       exit(0);
+}
+
+void
+makemsg(fname)
+       char *fname;
+{
+       register int ch, cnt;
+       struct tm *lt;
+       struct passwd *pw;
+       struct stat sbuf;
+       time_t now, time();
+       FILE *fp;
+       int fd;
+       char *p, *whom, hostname[MAXHOSTNAMELEN], lbuf[100], tmpname[15];
+       char *getlogin(), *strcpy(), *ttyname();
+
+       (void)strcpy(tmpname, _PATH_TMP);
+       (void)strcat(tmpname, "/wall.XXXXXX");
+       if (!(fd = mkstemp(tmpname)) || !(fp = fdopen(fd, "r+"))) {
+               (void)fprintf(stderr, "wall: can't open temporary file.\n");
+               exit(1);
+       }
+       (void)unlink(tmpname);
+
+       if (!nobanner) {
+               if (!(whom = getlogin()))
+                       whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
+               (void)gethostname(hostname, sizeof(hostname));
+               (void)time(&now);
+               lt = localtime(&now);
+
+               /*
+                * all this stuff is to blank out a square for the message;
+                * we wrap message lines at column 79, not 80, because some
+                * terminals wrap after 79, some do not, and we can't tell.
+                * Which means that we may leave a non-blank character
+                * in column 80, but that can't be helped.
+                */
+               (void)fprintf(fp, "\r%79s\r\n", " ");
+               (void)sprintf(lbuf, "Broadcast Message from %s@%s",
+                   whom, hostname);
+               (void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf);
+               (void)sprintf(lbuf, "        (%s) at %d:%02d ...", ttyname(2),
+                   lt->tm_hour, lt->tm_min);
+               (void)fprintf(fp, "%-79.79s\r\n", lbuf);
+       }
+       (void)fprintf(fp, "%79s\r\n", " ");
+
+       if (fname && !(freopen(fname, "r", stdin))) {
+               (void)fprintf(stderr, "wall: can't read %s.\n", fname);
+               exit(1);
+       }
+       while (fgets(lbuf, sizeof(lbuf), stdin))
+               for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
+                       if (cnt == 79 || ch == '\n') {
+                               for (; cnt < 79; ++cnt)
+                                       putc(' ', fp);
+                               putc('\r', fp);
+                               putc('\n', fp);
+                               cnt = 0;
+                       } else
+                               putc(ch, fp);
+               }
+       (void)fprintf(fp, "%79s\r\n", " ");
+       rewind(fp);
+
+       if (fstat(fd, &sbuf)) {
+               (void)fprintf(stderr, "wall: can't stat temporary file.\n");
+               exit(1);
+       }
+       mbufsize = sbuf.st_size;
+       if (!(mbuf = malloc((u_int)mbufsize))) {
+               (void)fprintf(stderr, "wall: out of memory.\n");
+               exit(1);
+       }
+       if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) {
+               (void)fprintf(stderr, "wall: can't read temporary file.\n");
+               exit(1);
+       }
+       (void)close(fd);
+}
diff --git a/ypbind.tproj/Makefile b/ypbind.tproj/Makefile
new file mode 100644 (file)
index 0000000..548fccf
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ypbind
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ypbind.c
+
+OTHERSRCS = Makefile Makefile.dist Makefile.postamble Makefile.preamble\
+            yp.x
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ypbind.tproj/Makefile.dist b/ypbind.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..901e614
--- /dev/null
@@ -0,0 +1,8 @@
+#      from: @(#)Makefile      5.8 (Berkeley) 7/28/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:00 wsanchez Exp $
+
+PROG=  ypbind
+NOMAN=
+CFLAGS+=-DDAEMON -DHEURISTIC
+
+.include <bsd.prog.mk>
diff --git a/ypbind.tproj/Makefile.postamble b/ypbind.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..cc6d6ab
--- /dev/null
@@ -0,0 +1,108 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A      # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1 # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+STRIPFLAGS =
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+
diff --git a/ypbind.tproj/Makefile.preamble b/ypbind.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..5ca4df3
--- /dev/null
@@ -0,0 +1,129 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES = yp.x
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
diff --git a/ypbind.tproj/PB.project b/ypbind.tproj/PB.project
new file mode 100644 (file)
index 0000000..dba6980
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (ypbind.c); 
+        OTHER_SOURCES = (Makefile, Makefile.dist, Makefile.postamble, Makefile.preamble, yp.x); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ypbind; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ypbind.tproj/yp.x b/ypbind.tproj/yp.x
new file mode 100644 (file)
index 0000000..cf2be0c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <rpcsvc/yp.x>
diff --git a/ypbind.tproj/ypbind.c b/ypbind.tproj/ypbind.c
new file mode 100644 (file)
index 0000000..bad58c0
--- /dev/null
@@ -0,0 +1,1289 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$Id: ypbind.c,v 1.1.1.1 1999/05/02 03:59:00 wsanchez Exp $";
+#endif
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <netdb.h>
+#include <string.h>
+#include <err.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_rmt.h>
+#include <unistd.h>
+#include <rpcsvc/yp.h>
+// #include <rpcsvc/yp_prot.h>
+// #include <rpcsvc/ypclnt.h>
+
+#define _PATH_YPBIND_LOCK "/var/run/ypbind.lock"
+#define YPSERVERSSUFF  ".ypservers"
+#define BINDINGDIR     "/var/yp/binding"
+
+#ifndef O_SHLOCK
+#define O_SHLOCK 0
+#endif
+
+#define BUFSIZE                1400
+
+struct _dom_binding
+{
+       struct _dom_binding *dom_pnext;
+       char dom_domain[YPMAXDOMAIN + 1];
+       struct sockaddr_in dom_server_addr;
+       unsigned short int dom_server_port;
+       int dom_socket;
+       CLIENT *dom_client;
+       long dom_vers;
+       time_t dom_check_t;
+       time_t dom_ask_t;
+       int dom_lockfd;
+       int dom_alive;
+       u_int32_t dom_xid;
+};
+
+static char *dname;
+
+static struct _dom_binding *ypbindlist;
+static int check;
+
+typedef enum
+{
+       YPBIND_DIRECT,
+       YPBIND_BROADCAST,
+       YPBIND_SETLOCAL,
+       YPBIND_SETALL
+} ypbind_mode_t;
+
+ypbind_mode_t ypbindmode;
+
+/*
+ * If ypbindmode is YPBIND_SETLOCAL or YPBIND_SETALL, this indicates
+ * whether or not we've been "ypset".  If we haven't, we behave like
+ * YPBIND_BROADCAST.  If we have, we behave like YPBIND_DIRECT.
+ */
+int been_ypset;
+
+static int insecure;
+static int rpcsock, pingsock;
+static struct rmtcallargs rmtca;
+static struct rmtcallres rmtcr;
+static bool_t rmtcr_outval;
+static u_long rmtcr_port;
+static SVCXPRT *udptransp, *tcptransp;
+
+int    main __P((int, char *[]));
+
+static void usage __P((void));
+static struct _dom_binding *makebinding __P((const char *));
+static int makelock __P((struct _dom_binding *));
+static void removelock __P((struct _dom_binding *));
+static void checkwork __P((void));
+static int ping __P((struct _dom_binding *));
+static int nag_servers __P((struct _dom_binding *));
+static enum clnt_stat handle_replies __P((void));
+static enum clnt_stat handle_ping __P((void));
+static void rpc_received __P((char *, struct sockaddr_in *, int));
+static struct _dom_binding *xid2ypdb __P((u_int32_t));
+static u_int32_t unique_xid __P((struct _dom_binding *));
+static int broadcast __P((char *, int));
+static int direct __P((char *, int));
+static int direct_set __P((char *, int, struct _dom_binding *));
+
+#define DEBUG_NONE 0
+#define DEBUG_STDERR 1
+#define DEBUG_SYSLOG 2
+
+static int debug;
+static char *msg_str = NULL;
+
+void
+sys_openlog(int debug, char *str, int flags, int facility)
+{
+       if (msg_str != NULL) free(msg_str);
+       msg_str = NULL;
+       if (str != NULL)
+       {
+               msg_str = malloc(strlen(str) + 1);
+               strcpy(msg_str, str);
+       }
+
+       if (debug & DEBUG_SYSLOG) openlog(msg_str, flags, facility);
+}
+
+void
+sys_msg(int debug, int priority, char *message, ...)
+{
+       va_list ap;
+
+       va_start(ap, message);
+
+       if (debug & DEBUG_SYSLOG) vsyslog(priority, message, ap);
+
+       if (debug & DEBUG_STDERR)
+       {
+               if (msg_str != NULL) fprintf(stderr, "%s: ", msg_str);
+               vfprintf(stderr, message, ap);
+               fprintf(stderr, "\n");
+               fflush(stderr);
+       }
+
+       va_end(ap);
+}
+
+static void
+usage()
+{
+       fprintf(stderr,
+           "Usage: ypbind [-broadcast] [-insecure] [-ypset] [-ypsetme] [-d]\n");
+       exit(1);
+}
+       
+static struct _dom_binding *
+makebinding(const char *dm)
+{
+       struct _dom_binding *ypdb;
+
+       ypdb = (struct _dom_binding *)malloc(sizeof *ypdb);
+       memset(ypdb, 0, sizeof *ypdb);
+       strncpy(ypdb->dom_domain, dm, sizeof ypdb->dom_domain);
+       ypdb->dom_domain[sizeof(ypdb->dom_domain) - 1] = '\0';
+
+       return ypdb;
+}
+
+static int
+makelock(struct _dom_binding *ypdb)
+{
+       int fd;
+       char path[MAXPATHLEN];
+
+       snprintf(path, sizeof(path), "%s/%s.%ld", BINDINGDIR,
+           ypdb->dom_domain, ypdb->dom_vers);
+
+       fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644);
+       if (fd == -1)
+       {
+               mkdir(BINDINGDIR, 0755);
+               fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644);
+               if (fd == -1) return -1;
+       }
+
+#if O_SHLOCK == 0
+       flock(fd, LOCK_SH);
+#endif
+       return fd;
+}
+
+static void
+removelock(struct _dom_binding *ypdb)
+{
+       char path[MAXPATHLEN];
+
+       snprintf(path, sizeof(path), "%s/%s.%ld",
+           BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers);
+       unlink(path);
+}
+
+static void *
+svc_ypbindproc_null_2(void *argp, SVCXPRT *transp)
+{
+       static char res;
+
+       sys_msg(debug, LOG_DEBUG, "ypbindproc_null_2");
+
+       memset(&res, 0, sizeof(res));
+       return (void *)&res;
+}
+
+static void *
+svc_ypbindproc_domain_2(void *argp, SVCXPRT *transp)
+{
+       static struct ypbind_resp res;
+       struct _dom_binding *ypdb;
+       char *arg = *(char **) argp;
+       int count;
+
+       sys_msg(debug, LOG_DEBUG, "ypbindproc_domain_2 %s", arg);
+
+       memset(&res, 0, sizeof res);
+       res.ypbind_status = YPBIND_FAIL_VAL;
+
+       for (count = 0, ypdb = ypbindlist;
+               ypdb != NULL;
+               ypdb = ypdb->dom_pnext, count++)
+       {
+               /* prevent denial of service */
+               if (count > 100) return NULL;
+               if (!strcmp(ypdb->dom_domain, arg)) break;
+       }
+
+       if (ypdb == NULL)
+       {
+               ypdb = makebinding(arg);
+               ypdb->dom_vers = YPVERS;
+               ypdb->dom_alive = 0;
+               ypdb->dom_lockfd = -1;
+               removelock(ypdb);
+               ypdb->dom_xid = unique_xid(ypdb);
+               ypdb->dom_pnext = ypbindlist;
+               ypbindlist = ypdb;
+               check++;
+               sys_msg(debug, LOG_ERR, "unknown domain %s", arg);
+               return NULL;
+       }
+
+       if (ypdb->dom_alive == 0)
+       {
+               sys_msg(debug, LOG_ERR, "dead domain %s", arg);
+               return NULL;
+       }
+
+#ifdef HEURISTIC
+       time(&now);
+       if (now < ypdb->dom_ask_t + 5)
+       {
+               /*
+                * Hmm. More than 2 requests in 5 seconds have indicated
+                * that my binding is possibly incorrect.
+                * Ok, do an immediate poll of the server.
+                */
+               if (ypdb->dom_check_t >= now)
+               {
+                       /* don't flood it */
+                       ypdb->dom_check_t = 0;
+                       check++;
+               }
+       }
+       ypdb->dom_ask_t = now;
+#endif
+
+       res.ypbind_status = YPBIND_SUCC_VAL;
+       bcopy(&ypdb->dom_server_addr.sin_addr.s_addr,
+               res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 4);
+       bcopy(&ypdb->dom_server_port,
+               res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 2);
+
+       sys_msg(debug, LOG_DEBUG, "domain %s at %s/%d", ypdb->dom_domain,
+                   inet_ntoa(ypdb->dom_server_addr.sin_addr),
+                   ntohs(ypdb->dom_server_addr.sin_port));
+       return &res;
+}
+
+static void *
+svc_ypbindproc_setdom_2(void *argp, SVCXPRT *transp)
+{
+       struct ypbind_setdom *sd = argp;
+       struct sockaddr_in *fromsin, bindsin;
+       static bool_t res;
+
+       memset(&bindsin, 0, sizeof bindsin);
+       bindsin.sin_family = AF_INET;
+       bindsin.sin_len = sizeof(bindsin);
+       bcopy(&sd->ypsetdom_binding.ypbind_binding_addr,
+               &bindsin.sin_addr.s_addr, 4);
+       bcopy(&sd->ypsetdom_binding.ypbind_binding_port,
+               &bindsin.sin_port, 2);
+       fromsin = svc_getcaller(transp);
+
+       memset(&res, 0, sizeof(res));
+
+       switch (ypbindmode)
+       {
+               case YPBIND_SETLOCAL:
+                       if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
+                       {
+                               sys_msg(debug, LOG_ERR, "ypset from %s denied",
+                                       inet_ntoa(fromsin->sin_addr));
+                               return NULL;
+                       }
+
+               /* FALLTHROUGH */
+
+               case YPBIND_SETALL:
+                       been_ypset = 1;
+                       break;
+
+               case YPBIND_DIRECT:
+               case YPBIND_BROADCAST:
+               default:
+                       sys_msg(debug, LOG_ERR, "ypset denied");
+                       return NULL;
+       }
+
+       if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED)
+       {
+               sys_msg(debug, LOG_ERR, "ypset from unpriviledged port denied");
+               return &res;
+       }
+
+       if (sd->ypsetdom_vers != YPVERS)
+       {
+               sys_msg(debug, LOG_ERR, "ypset with wrong version denied");
+               sys_msg(debug, LOG_DEBUG, "ypsetdom_vers = %lu   YPVERS = %lu",
+                       sd->ypsetdom_vers, YPVERS);
+               return &res;
+       }
+
+       rpc_received(sd->ypsetdom_domain, &bindsin, 1);
+
+       sys_msg(debug, LOG_DEBUG, "ypset to %s succeeded",
+               inet_ntoa(bindsin.sin_addr));
+       res = 1;
+       return &res;
+}
+
+static void
+ypbindprog_2(struct svc_req *rqstp,    register SVCXPRT *transp)
+{
+       union
+       {
+               char ypbindproc_domain_2_arg[YPMAXDOMAIN + 1];
+               struct ypbind_setdom ypbindproc_setdom_2_arg;
+       } argument;
+       struct authunix_parms *creds;
+       char *result;
+       xdrproc_t xdr_argument, xdr_result;
+       void *(*local) __P((void *, SVCXPRT *));
+
+       switch (rqstp->rq_proc)
+       {
+               case YPBINDPROC_NULL:
+                       xdr_argument = xdr_void;
+                       xdr_result = xdr_void;
+                       local = svc_ypbindproc_null_2;
+                       break;
+
+               case YPBINDPROC_DOMAIN:
+                       xdr_argument = xdr_domainname;
+                       xdr_result = xdr_ypbind_resp;
+                       local = svc_ypbindproc_domain_2;
+                       break;
+
+               case YPBINDPROC_SETDOM:
+                       switch (rqstp->rq_cred.oa_flavor)
+                       {
+                               case AUTH_UNIX:
+                                       creds = (struct authunix_parms *)rqstp->rq_clntcred;
+                                       if (creds->aup_uid != 0)
+                                       {
+                                               svcerr_auth(transp, AUTH_BADCRED);
+                                               return;
+                                       }
+                                       break;
+
+                               default:
+                                       svcerr_auth(transp, AUTH_TOOWEAK);
+                                       return;
+                       }
+
+                       xdr_argument = xdr_ypbind_setdom;
+                       xdr_result = xdr_void;
+                       local = svc_ypbindproc_setdom_2;
+                       break;
+
+               default:
+                       svcerr_noproc(transp);
+                       return;
+       }
+               
+       memset(&argument, 0, sizeof(argument));
+       if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument))
+       {
+               svcerr_decode(transp);
+               return;
+       }
+       
+       result = (*local)(&argument, transp);
+       if (result != NULL && !svc_sendreply(transp, xdr_result, result))
+       {
+               svcerr_systemerr(transp);
+       }
+
+       return;
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct timeval tv;
+       fd_set fdsr;
+       int width, lockfd;
+       int evil = 0, one, i;
+       char pathname[MAXPATHLEN];
+       struct stat st;
+
+       yp_get_default_domain(&dname);
+       if (dname[0] == '\0')
+       {
+               fprintf(stderr, "Domainname not set. Aborting.\n");
+               exit(1);
+       }
+
+       debug = DEBUG_SYSLOG;
+       ypbindmode = YPBIND_DIRECT;
+       for (i = 1; i < argc; i++)
+       {
+               if (!strcmp(argv[i], "-insecure"))
+                       insecure = 1;
+
+               else if (!strcmp(argv[i], "-ypset"))
+                       ypbindmode = YPBIND_SETALL;
+
+               else if (!strcmp(argv[i], "-ypsetme"))
+                       ypbindmode = YPBIND_SETLOCAL;
+
+               else if (!strcmp(argv[i], "-broadcast"))
+                       ypbindmode = YPBIND_BROADCAST;
+
+               else if (!strcmp(argv[i], "-d"))
+                       debug = DEBUG_STDERR;
+
+               else
+                       usage();
+       }
+
+       sys_openlog(debug, "ypbind", LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
+       /*
+        * Per traditional ypbind(8) semantics, if a ypservers
+        * file does not exist, we default to broadcast mode.
+        * If the file does exist, we default to direct mode.
+        * Note that we can still override direct mode by passing
+        * the -broadcast flag.
+        */
+       snprintf(pathname, sizeof(pathname), "%s/%s%s",
+               BINDINGDIR, dname, YPSERVERSSUFF);
+               
+       if ((ypbindmode == YPBIND_DIRECT) && (stat(pathname, &st) < 0))
+       {
+               sys_msg(debug, LOG_DEBUG, "%s does not exist, defaulting to broadcast.",
+                       pathname);
+               ypbindmode = YPBIND_BROADCAST;
+       }
+       
+       /* blow away everything in BINDINGDIR */
+
+       lockfd = open(_PATH_YPBIND_LOCK, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644);
+       if (lockfd == -1)
+       {
+               sys_msg(debug, LOG_ERR, "Cannot create %s", _PATH_YPBIND_LOCK);
+               exit(1);
+       }
+
+#if O_SHLOCK == 0
+       flock(lockfd, LOCK_SH);
+#endif
+
+       pmap_unset(YPBINDPROG, YPBINDVERS);
+
+       udptransp = svcudp_create(RPC_ANYSOCK);
+       if (udptransp == NULL)
+       {
+               sys_msg(debug, LOG_ERR, "Cannot create udp service.");
+               exit(1);
+       }
+
+       if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2,
+           IPPROTO_UDP))
+       {
+               sys_msg(debug, LOG_ERR,
+                       "Unable to register (YPBINDPROG, YPBINDVERS, udp).");
+               exit(1);
+       }
+
+       tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0);
+       if (tcptransp == NULL)
+       {
+               sys_msg(debug, LOG_ERR, "Cannot create tcp service.");
+               exit(1);
+       }
+
+       if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2,
+           IPPROTO_TCP))
+       {
+               sys_msg(debug, LOG_ERR,
+                       "Unable to register (YPBINDPROG, YPBINDVERS, tcp).");
+               exit(1);
+       }
+
+       /* XXX use SOCK_STREAM for direct queries? */
+       rpcsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (rpcsock == -1)
+       {
+               sys_msg(debug, LOG_ERR, "rpc socket() failed.");
+               exit(1);
+       }
+
+       pingsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (pingsock == -1)
+       {
+               sys_msg(debug, LOG_ERR, "ping socket() failed.");
+               exit(1);
+       }
+       
+       fcntl(rpcsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY);
+       fcntl(pingsock, F_SETFL, fcntl(pingsock, F_GETFL, 0) | FNDELAY);
+
+       one = 1;
+       setsockopt(rpcsock, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
+       rmtca.prog = YPPROG;
+       rmtca.vers = YPVERS;
+       rmtca.proc = YPPROC_DOMAIN_NONACK;
+       rmtca.xdr_args = NULL;          /* set at call time */
+       rmtca.args_ptr = NULL;          /* set at call time */
+       rmtcr.port_ptr = &rmtcr_port;
+       rmtcr.xdr_results = xdr_bool;
+       rmtcr.results_ptr = (caddr_t)&rmtcr_outval;
+
+       /* build initial domain binding, make it "unsuccessful" */
+       ypbindlist = makebinding(dname);
+       ypbindlist->dom_vers = YPVERS;
+       ypbindlist->dom_alive = 0;
+       ypbindlist->dom_lockfd = -1;
+       removelock(ypbindlist);
+
+       checkwork();
+
+//     width = svc_maxfd;
+       width = FD_SETSIZE;
+       width = 32;
+       if (rpcsock > width)
+               width = rpcsock;
+       if (pingsock > width)
+               width = pingsock;
+       width++;
+
+       for (;;)
+       {
+               fdsr = svc_fdset;
+               FD_SET(rpcsock, &fdsr);
+               FD_SET(pingsock, &fdsr);
+               tv.tv_sec = 1;
+               tv.tv_usec = 0;
+
+               switch (select(width, &fdsr, NULL, NULL, &tv))
+               {
+                       case 0:
+                               checkwork();
+                               break;
+
+                       case -1:
+                               sys_msg(debug, LOG_WARNING, "select: %s", strerror(errno));
+                               break;
+
+                       default:
+                               if (FD_ISSET(rpcsock, &fdsr)) handle_replies();
+                               if (FD_ISSET(pingsock, &fdsr)) handle_ping();
+                               svc_getreqset(&fdsr);
+                               if (check) checkwork();
+                               break;
+               }
+
+               if ((evil == 0) && (ypbindlist->dom_alive != 0))
+               {
+                       evil = 1;
+                       if (debug == DEBUG_SYSLOG) daemon(0, 0);
+               }
+       }
+}
+
+/*
+ * State transition is done like this: 
+ *
+ * STATE       EVENT           ACTION                  NEWSTATE        TIMEOUT
+ * no binding  timeout         broadcast               no binding      5 sec
+ * no binding  answer          --                      binding         60 sec
+ * binding     timeout         ping server             checking        5 sec
+ * checking    timeout         ping server + broadcast checking        5 sec
+ * checking    answer          --                      binding         60 sec
+ */
+void
+checkwork()
+{
+       struct _dom_binding *ypdb;
+       time_t t;
+
+       check = 0;
+
+       time(&t);
+       for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
+       {
+               if (ypdb->dom_check_t < t)
+               {
+                       if (ypdb->dom_alive == 1) ping(ypdb);
+                       else nag_servers(ypdb);
+                       time(&t);
+                       ypdb->dom_check_t = t + 5;
+               }
+       }
+}
+
+int
+ping(struct _dom_binding *ypdb)
+{
+       char *dom = ypdb->dom_domain;
+       struct rpc_msg msg;
+       char buf[BUFSIZE];
+       enum clnt_stat st;
+       int outlen;
+       AUTH *rpcua;
+       XDR xdr;
+
+       memset(&xdr, 0, sizeof xdr);
+       memset(&msg, 0, sizeof msg);
+
+       rpcua = authunix_create_default();
+       if (rpcua == NULL)
+       {
+               sys_msg(debug, LOG_ERR, "ping: cannot get unix auth");
+               return RPC_SYSTEMERROR;
+       }
+
+       msg.rm_direction = CALL;
+       msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+       msg.rm_call.cb_prog = YPPROG;
+       msg.rm_call.cb_vers = YPVERS;
+       msg.rm_call.cb_proc = YPPROC_DOMAIN_NONACK;
+       msg.rm_call.cb_cred = rpcua->ah_cred;
+       msg.rm_call.cb_verf = rpcua->ah_verf;
+
+       msg.rm_xid = ypdb->dom_xid;
+       xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE);
+       if (!xdr_callmsg(&xdr, &msg))
+       {
+               st = RPC_CANTENCODEARGS;
+               AUTH_DESTROY(rpcua);
+               return st;
+       }
+
+       if (!xdr_domainname(&xdr, (void *)&dom))
+       {
+               st = RPC_CANTENCODEARGS;
+               AUTH_DESTROY(rpcua);
+               return st;
+       }
+
+       outlen = (int)xdr_getpos(&xdr);
+       xdr_destroy(&xdr);
+       if (outlen < 1)
+       {
+               st = RPC_CANTENCODEARGS;
+               AUTH_DESTROY(rpcua);
+               return st;
+       }
+
+       AUTH_DESTROY(rpcua);
+
+       ypdb->dom_alive = 2;
+       if (sendto(pingsock, buf, outlen, 0, 
+                  (struct sockaddr *)&ypdb->dom_server_addr,
+                  sizeof ypdb->dom_server_addr) == -1)
+               sys_msg(debug, LOG_WARNING, "ping: sendto");
+       return 0;
+
+}
+
+static int
+nag_servers(struct _dom_binding *ypdb)
+{
+       char *dom = ypdb->dom_domain;
+       struct rpc_msg msg;
+       char buf[BUFSIZE];
+       enum clnt_stat st;
+       int outlen;
+       AUTH *rpcua;
+       XDR xdr;
+
+       rmtca.xdr_args = xdr_domainname;
+       rmtca.args_ptr = (char *)&dom;
+
+       memset(&xdr, 0, sizeof xdr);
+       memset(&msg, 0, sizeof msg);
+
+       rpcua = authunix_create_default();
+       if (rpcua == NULL)
+       {
+               sys_msg(debug, LOG_ERR, "ping: cannot get unix auth");
+               return RPC_SYSTEMERROR;
+       }
+
+       msg.rm_direction = CALL;
+       msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+       msg.rm_call.cb_prog = PMAPPROG;
+       msg.rm_call.cb_vers = PMAPVERS;
+       msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+       msg.rm_call.cb_cred = rpcua->ah_cred;
+       msg.rm_call.cb_verf = rpcua->ah_verf;
+
+       msg.rm_xid = ypdb->dom_xid;
+       xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE);
+       if (!xdr_callmsg(&xdr, &msg))
+       {
+               st = RPC_CANTENCODEARGS;
+               AUTH_DESTROY(rpcua);
+               return st;
+       }
+
+       if (!xdr_rmtcall_args(&xdr, &rmtca))
+       {
+               st = RPC_CANTENCODEARGS;
+               AUTH_DESTROY(rpcua);
+               return st;
+       }
+
+       outlen = (int)xdr_getpos(&xdr);
+       xdr_destroy(&xdr);
+       if (outlen < 1)
+       {
+               st = RPC_CANTENCODEARGS;
+               AUTH_DESTROY(rpcua);
+               return st;
+       }
+
+       AUTH_DESTROY(rpcua);
+
+       if (ypdb->dom_lockfd != -1)
+       {
+               close(ypdb->dom_lockfd);
+               ypdb->dom_lockfd = -1;
+               removelock(ypdb);
+       }
+
+       if (ypdb->dom_alive == 2)
+       {
+               /*
+                * This resolves the following situation:
+                * ypserver on other subnet was once bound,
+                * but rebooted and is now using a different port
+                */
+               struct sockaddr_in bindsin;
+
+               memset(&bindsin, 0, sizeof bindsin);
+               bindsin.sin_family = AF_INET;
+               bindsin.sin_len = sizeof(bindsin);
+               bindsin.sin_port = htons(PMAPPORT);
+               bindsin.sin_addr = ypdb->dom_server_addr.sin_addr;
+
+               if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
+                          sizeof bindsin) == -1)
+                       sys_msg(debug, LOG_WARNING, "broadcast: sendto");
+       }
+
+       switch (ypbindmode)
+       {
+               case YPBIND_SETALL:
+               case YPBIND_SETLOCAL:
+                       if (been_ypset) return direct_set(buf, outlen, ypdb);
+                       /* FALLTHROUGH */
+
+               case YPBIND_BROADCAST:
+                       return broadcast(buf, outlen);
+
+               case YPBIND_DIRECT:
+                       return direct(buf, outlen);
+       }
+
+       return -1;
+}
+
+static int
+broadcast(char *buf, int outlen)
+{
+       struct ifconf ifc;
+       struct ifreq *ifr;
+       int offset, addrlen;
+       struct in_addr in;
+       int sock;
+       char inbuf[8192];
+       struct sockaddr_in bindsin;
+
+       /* find all networks and send the RPC packet out them all */
+       sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (sock == -1)
+       {
+               sys_msg(debug, LOG_WARNING, "broadcast: socket: %s", strerror(errno));
+               return -1;
+       }
+
+       memset(&bindsin, 0, sizeof bindsin);
+       bindsin.sin_family = AF_INET;
+       bindsin.sin_len = sizeof(bindsin);
+       bindsin.sin_port = htons(PMAPPORT);
+
+       ifc.ifc_len = sizeof inbuf;
+       ifc.ifc_buf = inbuf;
+       if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
+       {
+               close(sock);
+               sys_msg(debug, LOG_WARNING, "broadcast: ioctl(SIOCGIFCONF): %s",
+                       strerror(errno));
+               return -1;
+       }
+
+       addrlen = sizeof(struct ifreq) - IFNAMSIZ;
+       offset = 0;
+
+       while (offset <= ifc.ifc_len)
+       {
+               ifr = (struct ifreq *)(ifc.ifc_buf + offset);
+               offset += IFNAMSIZ;
+               if (ifr->ifr_addr.sa_len > addrlen) offset += ifr->ifr_addr.sa_len;
+               else offset += addrlen;
+
+               if (ifr->ifr_addr.sa_family != AF_INET) continue;
+               if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) continue;
+               if ((ifr->ifr_flags & IFF_UP) == 0) continue;
+
+               if (ifr->ifr_flags & IFF_BROADCAST)
+               {
+                       if (ioctl(sock, SIOCGIFBRDADDR, ifr) < 0)
+                       {
+                               sys_msg(debug, LOG_WARNING,
+                                       "broadcast: ioctl(SIOCGIFBRDADDR): %s", strerror(errno));
+                               continue;
+                       }
+               }
+               else if (ifr->ifr_flags & IFF_LOOPBACK)
+               {
+                       if (ioctl(sock, SIOCGIFADDR, ifr) < 0)
+                       {
+                               sys_msg(debug, LOG_WARNING,
+                                       "broadcast: ioctl(SIOCGIFADDR): %s", strerror(errno));
+                               continue;
+                       }
+               }
+               else continue;
+
+               in = ((struct sockaddr_in *)&(ifr->ifr_addr))->sin_addr;
+               bindsin.sin_addr = in;
+               if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
+                          sizeof bindsin) == -1)
+                       sys_msg(debug, LOG_WARNING, "broadcast: sendto: %s",
+                               strerror(errno));
+       }
+
+       close(sock);
+       return 0;
+}
+
+static int
+direct(char *buf, int outlen)
+{
+       static FILE *df;
+       static char ypservers_path[MAXPATHLEN];
+       char line[_POSIX2_LINE_MAX];
+       char *p;
+       struct hostent *hp;
+       struct sockaddr_in bindsin;
+       int i, count = 0;
+
+       if (df) rewind(df);
+       else {
+               snprintf(ypservers_path, sizeof(ypservers_path),
+                   "%s/%s%s", BINDINGDIR, dname, YPSERVERSSUFF);
+               df = fopen(ypservers_path, "r");
+               if (df == NULL)
+               {
+                       sys_msg(debug, LOG_ALERT, "Missing file %s, aborting.",
+                               ypservers_path);
+                       exit(1);
+               }
+       }
+
+       memset(&bindsin, 0, sizeof bindsin);
+       bindsin.sin_family = AF_INET;
+       bindsin.sin_len = sizeof(bindsin);
+       bindsin.sin_port = htons(PMAPPORT);
+
+       while(fgets(line, sizeof(line), df) != NULL)
+       {
+               /* skip lines that are too big */
+               p = strchr(line, '\n');
+               if (p == NULL)
+               {
+                       int c;
+
+                       while ((c = getc(df)) != '\n' && c != EOF);
+                       continue;
+               }
+
+               *p = '\0';
+               p = line;
+               while (isspace(*p)) p++;
+               if (*p == '#') continue;
+               hp = gethostbyname(p);
+               if (hp == NULL)
+               {
+                       sys_msg(debug, LOG_ERR, "Can't find host: %s", p);
+                       continue;
+               }
+       
+               /* step through all addresses in case first is unavailable */
+               for (i = 0; hp->h_addr_list[i]; i++)
+               {
+                       memmove(&bindsin.sin_addr, hp->h_addr_list[0],
+                           hp->h_length);
+                       if (sendto(rpcsock, buf, outlen, 0,
+                           (struct sockaddr *)&bindsin, sizeof bindsin) < 0)
+                       {
+                               sys_msg(debug, LOG_WARNING, "direct: sendto: %s",
+                                       strerror(errno));
+                               continue;
+                       }
+                       else count++;
+               }
+       }
+       
+       if (count == 0)
+       {
+               sys_msg(debug, LOG_ALERT,
+                       "Can't contact any servers listed in %s.  Aborting", ypservers_path);
+               exit(1);
+       }
+
+       return 0;
+}
+
+static int
+direct_set(char *buf, int outlen, struct _dom_binding *ypdb)
+{
+       struct sockaddr_in bindsin;
+       char path[MAXPATHLEN];
+       struct iovec iov[2];
+       struct ypbind_resp ybr;
+       SVCXPRT dummy_svc;
+       int fd, bytes;
+
+       /*
+        * Gack, we lose if binding file went away.  We reset
+        * "been_set" if this happens, otherwise we'll never
+        * bind again.
+        */
+       snprintf(path, sizeof(path), "%s/%s.%ld", BINDINGDIR,
+           ypdb->dom_domain, ypdb->dom_vers);
+
+       if ((fd = open(path, O_SHLOCK|O_RDONLY, 0644)) == -1)
+       {
+               sys_msg(debug, LOG_WARNING, "Can't open file %s", path);
+               been_ypset = 0;
+               return -1;
+       }
+
+#if O_SHLOCK == 0
+       flock(fd, LOCK_SH);
+#endif
+
+       /* Read the binding file... */
+       iov[0].iov_base = (caddr_t)&(dummy_svc.xp_port);
+       iov[0].iov_len = sizeof(dummy_svc.xp_port);
+       iov[1].iov_base = (caddr_t)&ybr;
+       iov[1].iov_len = sizeof(ybr);
+       bytes = readv(fd, iov, 2);
+       close(fd);
+
+       if (bytes != (iov[0].iov_len + iov[1].iov_len))
+       {
+               /* Binding file corrupt? */
+               sys_msg(debug, LOG_WARNING, "Can't parse file %s", path);
+               been_ypset = 0;
+               return -1;
+       }
+
+       bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+               &bindsin.sin_addr, 4);
+
+       if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
+           sizeof(bindsin)) < 0)
+       {
+               sys_msg(debug, LOG_WARNING, "direct_set: sendto: %s", strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
+static enum clnt_stat
+handle_replies()
+{
+       char buf[BUFSIZE];
+       int fromlen, inlen;
+       struct _dom_binding *ypdb;
+       struct sockaddr_in raddr;
+       struct rpc_msg msg;
+       XDR xdr;
+
+recv_again:
+       memset(&xdr, 0, sizeof(xdr));
+       memset(&msg, 0, sizeof(msg));
+       msg.acpted_rply.ar_verf = _null_auth;
+       msg.acpted_rply.ar_results.where = (caddr_t)&rmtcr;
+       msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
+
+try_again:
+       fromlen = sizeof (struct sockaddr);
+       inlen = recvfrom(rpcsock, buf, sizeof buf, 0,
+               (struct sockaddr *)&raddr, &fromlen);
+       if (inlen < 0)
+       {
+               if (errno == EINTR) goto try_again;
+               return RPC_CANTRECV;
+       }
+
+       if (inlen < sizeof(u_int32_t)) goto recv_again;
+
+       /*
+        * see if reply transaction id matches sent id.
+        * If so, decode the results.
+        */
+       xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);
+       if (xdr_replymsg(&xdr, &msg))
+       {
+               if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+                   (msg.acpted_rply.ar_stat == SUCCESS)) {
+                       raddr.sin_port = htons((u_short)rmtcr_port);
+                       ypdb = xid2ypdb(msg.rm_xid);
+                       if (ypdb != NULL) rpc_received(ypdb->dom_domain, &raddr, 0);
+               }
+       }
+
+       xdr.x_op = XDR_FREE;
+       msg.acpted_rply.ar_results.proc = xdr_void;
+       xdr_destroy(&xdr);
+
+       return RPC_SUCCESS;
+}
+
+static enum clnt_stat
+handle_ping()
+{
+       char buf[BUFSIZE];
+       int fromlen, inlen;
+       struct _dom_binding *ypdb;
+       struct sockaddr_in raddr;
+       struct rpc_msg msg;
+       XDR xdr;
+       bool_t res;
+
+recv_again:
+       memset(&xdr, 0, sizeof(xdr));
+       memset(&msg, 0, sizeof(msg));
+       msg.acpted_rply.ar_verf = _null_auth;
+       msg.acpted_rply.ar_results.where = (caddr_t)&res;
+       msg.acpted_rply.ar_results.proc = xdr_bool;
+
+try_again:
+       fromlen = sizeof (struct sockaddr);
+       inlen = recvfrom(pingsock, buf, sizeof buf, 0,
+               (struct sockaddr *)&raddr, &fromlen);
+       if (inlen < 0)
+       {
+               if (errno == EINTR) goto try_again;
+               return RPC_CANTRECV;
+       }
+
+       if (inlen < sizeof(u_int32_t)) goto recv_again;
+
+       /*
+        * see if reply transaction id matches sent id.
+        * If so, decode the results.
+        */
+       xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);
+       if (xdr_replymsg(&xdr, &msg))
+       {
+               if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+                   (msg.acpted_rply.ar_stat == SUCCESS))
+               {
+                       ypdb = xid2ypdb(msg.rm_xid);
+                       if (ypdb != NULL) rpc_received(ypdb->dom_domain, &raddr, 0);
+               }
+       }
+
+       xdr.x_op = XDR_FREE;
+       msg.acpted_rply.ar_results.proc = xdr_void;
+       xdr_destroy(&xdr);
+
+       return RPC_SUCCESS;
+}
+
+/*
+ * LOOPBACK IS MORE IMPORTANT: PUT IN HACK
+ */
+void
+rpc_received(char *dom, struct sockaddr_in *raddrp, int force)
+{
+       struct _dom_binding *ypdb;
+       struct iovec iov[2];
+       struct ypbind_resp ybr;
+       int fd;
+
+       sys_msg(debug, LOG_DEBUG, "returned from %s about %s",
+               inet_ntoa(raddrp->sin_addr), dom);
+
+       if (dom == NULL) return;
+
+       /* don't support insecure servers by default */
+       if (!insecure && ntohs(raddrp->sin_port) >= IPPORT_RESERVED) return;
+
+       for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
+       {
+               if (!strcmp(ypdb->dom_domain, dom)) break;
+       }
+
+       if (ypdb == NULL)
+       {
+               if (force == 0) return;
+               ypdb = makebinding(dom);
+               ypdb->dom_lockfd = -1;
+               ypdb->dom_pnext = ypbindlist;
+               ypbindlist = ypdb;
+       }
+
+       /* soft update, alive */
+       if (ypdb->dom_alive == 1 && force == 0)
+       {
+               if (!memcmp(&ypdb->dom_server_addr, raddrp,
+                       sizeof ypdb->dom_server_addr))
+               {
+                       ypdb->dom_alive = 1;
+                       /* recheck binding in 60 sec */
+                       ypdb->dom_check_t = time(NULL) + 60;
+               }
+               return;
+       }
+       
+       memcpy(&ypdb->dom_server_addr, raddrp, sizeof ypdb->dom_server_addr);
+       /* recheck binding in 60 seconds */
+       ypdb->dom_check_t = time(NULL) + 60;
+       ypdb->dom_vers = YPVERS;
+       ypdb->dom_alive = 1;
+
+       if (ypdb->dom_lockfd != -1) close(ypdb->dom_lockfd);
+
+       if ((fd = makelock(ypdb)) == -1) return;
+
+       /*
+        * ok, if BINDINGDIR exists, and we can create the binding file,
+        * then write to it..
+        */
+       ypdb->dom_lockfd = fd;
+
+       iov[0].iov_base = (caddr_t)&(udptransp->xp_port);
+       iov[0].iov_len = sizeof udptransp->xp_port;
+       iov[1].iov_base = (caddr_t)&ybr;
+       iov[1].iov_len = sizeof ybr;
+
+       memset(&ybr, 0, sizeof ybr);
+       ybr.ypbind_status = YPBIND_SUCC_VAL;
+       bcopy(&raddrp->sin_addr.s_addr,
+               ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 4);
+       bcopy(&raddrp->sin_port,
+               ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 2);
+       
+       if (writev(ypdb->dom_lockfd, iov, 2) !=
+           iov[0].iov_len + iov[1].iov_len)
+       {
+               sys_msg(debug, LOG_WARNING, "writev: %s", strerror(errno));
+               close(ypdb->dom_lockfd);
+               removelock(ypdb);
+               ypdb->dom_lockfd = -1;
+       }
+}
+
+static struct _dom_binding *
+xid2ypdb(u_int32_t xid)
+{
+       struct _dom_binding *ypdb;
+
+       for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
+       {
+               if (ypdb->dom_xid == xid) break;
+       }
+
+       return (ypdb);
+}
+
+static u_int32_t
+unique_xid(struct _dom_binding *ypdb)
+{
+       u_int32_t tmp_xid;
+
+       tmp_xid = (u_int32_t)(((u_long)ypdb) & 0xffffffff);
+       while (xid2ypdb(tmp_xid) != NULL) tmp_xid++;
+
+       return tmp_xid;
+}
diff --git a/ypcat.tproj/Makefile b/ypcat.tproj/Makefile
new file mode 100644 (file)
index 0000000..e3a8242
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ypcat
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ypcat.c
+
+OTHERSRCS = Makefile.dist Makefile.preamble ypcat.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ypcat.tproj/Makefile.dist b/ypcat.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..55b8f72
--- /dev/null
@@ -0,0 +1,6 @@
+#      from: @(#)Makefile      5.8 (Berkeley) 7/28/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:01 wsanchez Exp $
+
+PROG=  ypcat
+
+.include <bsd.prog.mk>
diff --git a/ypcat.tproj/Makefile.preamble b/ypcat.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/ypcat.tproj/PB.project b/ypcat.tproj/PB.project
new file mode 100644 (file)
index 0000000..fc90efc
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (ypcat.c); 
+        OTHER_SOURCES = (Makefile.dist, Makefile.preamble, ypcat.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ypcat; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ypcat.tproj/ypcat.1 b/ypcat.tproj/ypcat.1
new file mode 100644 (file)
index 0000000..529b3ee
--- /dev/null
@@ -0,0 +1,70 @@
+.\" Copyright (c) 1993 Winning Strategies, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software developed by Winning Strategies, Inc.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\"    $Id: ypcat.1,v 1.1.1.1 1999/05/02 03:59:01 wsanchez Exp $
+.\"
+.Dd December 3, 1993
+.Dt YPCAT 1
+.Os
+.Sh NAME
+.Nm ypcat
+.Nd "print the values of all keys in a YP database"
+.Sh SYNOPSIS
+.Nm ypcat
+.Op Fl kt
+.Op Fl d Ar domainname
+.Ar mapname
+.Nm ypcat 
+.Fl x
+.Sh DESCRIPTION
+.Nm Ypcat
+prints out the values of all keys from the 
+.Tn YP
+database specified by
+.Ar mapname,
+which may be a map name or a map nickname.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domainname
+Specify a domain other than the default domain.
+.It Fl k
+Display map keys.
+This option is useful with maps in which the values are null or the key
+is not part of the value.
+.It Fl t
+Inhibit translation of map nicknames
+to their corresponding map names.
+.It Fl x
+Display the map nickname table.
+.El
+.Sh SEE ALSO
+.Xr ypmatch 1 ,
+.Xr yp 8
+.Sh AUTHOR
+Theo De Raadt
diff --git a/ypcat.tproj/ypcat.c b/ypcat.tproj/ypcat.c
new file mode 100644 (file)
index 0000000..72e4e45
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$Id: ypcat.c,v 1.1.1.1 1999/05/02 03:59:01 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+struct ypalias {
+       char *alias, *name;
+} ypaliases[] = {
+       { "passwd", "passwd.byname" },
+       { "group", "group.byname" },
+       { "networks", "networks.byaddr" },
+       { "hosts", "hosts.byaddr" },
+       { "protocols", "protocols.bynumber" },
+       { "services", "services.byname" },
+       { "aliases", "mail.aliases" },
+       { "ethers", "ethers.byname" },
+};
+
+int key;
+
+usage()
+{
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\typcat [-k] [-d domainname] [-t] mapname\n");
+       fprintf(stderr, "\typcat -x\n");
+       exit(1);
+}
+
+printit(instatus, inkey, inkeylen, inval, invallen, indata)
+int instatus;
+char *inkey;
+int inkeylen;
+char *inval;
+int invallen;
+char *indata;
+{
+       if(instatus != YP_TRUE)
+               return instatus;
+       if(key)
+               printf("%*.*s ", inkeylen, inkeylen, inkey);
+       printf("%*.*s\n", invallen, invallen, inval);
+       return 0;
+}
+
+int
+main(argc, argv)
+char **argv;
+{
+       char *domainname;
+       struct ypall_callback ypcb;
+       char *inmap;
+       extern char *optarg;
+       extern int optind;
+       int notrans;
+       int c, r, i;
+
+       notrans = key = 0;
+       yp_get_default_domain(&domainname);
+
+       while( (c=getopt(argc, argv, "xd:kt")) != -1)
+               switch(c) {
+               case 'x':
+                       for(i=0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+                               printf("Use \"%s\" for \"%s\"\n",
+                                       ypaliases[i].alias,
+                                       ypaliases[i].name);
+                       exit(0);
+               case 'd':
+                       domainname = optarg;
+                       break;
+               case 't':
+                       notrans++;
+                       break;
+               case 'k':
+                       key++;
+                       break;
+               default:
+                       usage();
+               }
+
+       if(optind + 1 != argc )
+               usage();
+
+       inmap = argv[optind];
+       for(i=0; (!notrans) && i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+               if( strcmp(inmap, ypaliases[i].alias) == 0)
+                       inmap = ypaliases[i].name;
+       ypcb.foreach = printit;
+       ypcb.data = NULL;
+
+       r = yp_all(domainname, inmap, &ypcb);
+       switch(r) {
+       case 0:
+               break;
+       case YPERR_YPBIND:
+               fprintf(stderr, "ypcat: not running ypbind\n");
+               exit(1);
+       default:
+               fprintf(stderr, "No such map %s. Reason: %s\n",
+                       inmap, yperr_string(r));
+               exit(1);
+       }
+       exit(0);
+}
diff --git a/ypinit.tproj/Makefile b/ypinit.tproj/Makefile
new file mode 100644 (file)
index 0000000..4720077
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# RC Makefile for ypinit scripts on Rhapsody.
+#
+# $Id: Makefile,v 1.1.1.1 1999/05/02 03:59:01 wsanchez Exp $
+#
+
+VARYP=$(DSTROOT)/private/var/yp
+USRSBIN=$(DSTROOT)/usr/sbin
+
+PROJECT=ypinit.tproj
+
+.PHONY: all install installhdrs installsrc build clean recurse
+
+all: build
+
+##
+# Targets
+##
+       
+build: build_init
+
+build_init:
+       @echo "Building $(PROJECT)..."
+
+installsrc:
+       -mkdir -p $(SRCROOT)$(SRCPATH)
+       cp Makefile Makefile.yp Makefile.main ypinit.sh $(SRCROOT)$(SRCPATH)
+
+installhdrs:
+
+clean:
+
+install: install_makefiles install_binaries
+
+install_makefiles:
+       -mkdir -p $(VARYP)
+       install -c -m 644 Makefile.yp $(VARYP)
+       -chown root.wheel $(VARYP)/Makefile.yp
+       install -c -m 644 Makefile.main $(VARYP)
+       -chown root.wheel $(VARYP)/Makefile.main
+       
+install_binaries:
+       -mkdir -p $(USRSBIN)
+       install -c -m 755 ypinit.sh $(USRSBIN)
+       -chown root.wheel $(USRSBIN)/ypinit
+
diff --git a/ypinit.tproj/Makefile.main b/ypinit.tproj/Makefile.main
new file mode 100644 (file)
index 0000000..f691cd8
--- /dev/null
@@ -0,0 +1,6 @@
+
+SUBDIR=        
+
+all:
+       cd $(SUBDIR) && make all
+
diff --git a/ypinit.tproj/Makefile.yp b/ypinit.tproj/Makefile.yp
new file mode 100644 (file)
index 0000000..bed83a7
--- /dev/null
@@ -0,0 +1,327 @@
+YPDBDIR=/private/var/yp
+DIR=/etc
+AMDDIR=/etc/amd
+NOPUSH=""
+#
+AWK=/usr/bin/awk
+CAT=/bin/cat
+CP=/bin/cp
+RM=/bin/rm
+CUT=/usr/bin/cut
+ECHO=/bin/echo
+MAKEDBM=/usr/sbin/makedbm
+SED=/usr/bin/sed
+SENDMAIL=/usr/sbin/sendmail
+STDHOSTS=/usr/sbin/stdhosts
+STDETHERS=/usr/sbin/stdethers
+MKALIAS=/usr/sbin/mkalias
+MKNETID=/usr/sbin/mknetid
+REVNETGROUP=/usr/sbin/revnetgroup
+TOUCH=/usr/bin/touch
+PWD:=$(shell /bin/pwd)
+DOMAIN:=$(shell /usr/bin/basename $(PWD))
+YPPUSH=/usr/sbin/yppush
+
+# Password maps in standard YP is unsecure. This is due to the fact that
+# passwords are accessable for anyone.
+# As a solution, maps can be secure (makedbm -s). If a map is secure only
+# a privileged user can access it.
+MAKEDBM-S=$(MAKEDBM) -s
+UNSECURE="True"
+
+all: passwd group hosts ethers networks rpc services protocols netid netgroup aliases
+
+passwd.time: $(DIR)/master.passwd
+       -@if [ -f $(>) ]; then \
+               if [ ! $(UNSECURE) ]; then \
+                       $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 | \
+                       $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+                       { print $$1, $$1":*:"$$3":"$$4":"$$5":"$$6":"$$7 }' -|\
+                       $(MAKEDBM) - passwd.byname; \
+                       $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 |\
+                       $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+                       { print $$3, $$1":*:"$$3":"$$4":"$$5":"$$6":"$$7 }' -|\
+                       $(MAKEDBM) - passwd.byuid; \
+               else \
+                       $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 | \
+                       $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+                       { print $$1, $$0 }' - | $(MAKEDBM) - passwd.byname; \
+                       $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 |\
+                       $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+                       { print $$3, $$0 }' - | $(MAKEDBM) - passwd.byuid; \
+               fi; \
+               $(CAT) $(>) | \
+               $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+               { print $$1, $$0 }' - | $(MAKEDBM-S) - master.passwd.byname; \
+               $(CAT) $(>) | \
+               $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+               { print $$3, $$0 }' - | $(MAKEDBM-S) - master.passwd.byuid; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated passwd"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) passwd.byname; \
+                       $(YPPUSH) -d $(DOMAIN) passwd.byuid; \
+                       $(YPPUSH) -d $(DOMAIN) master.passwd.byname; \
+                       $(YPPUSH) -d $(DOMAIN) master.passwd.byuid; \
+                       $(ECHO) "pushed passwd"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+
+group.time: $(DIR)/group
+       -@if [ -f $(>) ]; then \
+               $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+               { print $$1, $$0 }' $(>) | \
+               $(MAKEDBM) - group.byname; \
+               $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \
+               { print $$3, $$0 }' $(>) | \
+               $(MAKEDBM) - group.bygid; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated group"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) group.byname; \
+                       $(YPPUSH) -d $(DOMAIN) group.bygid; \
+                       $(ECHO) "pushed group"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+hosts.time: $(DIR)/hosts
+       -@if [ -f $(DIR)/hosts ]; then \
+               $(STDHOSTS) $(>) | $(SED) -e s/#.*$$// | \
+               $(AWK) '{for (i = 2; i <= NF; i++) print $$i, $$0 }' | \
+               $(MAKEDBM) - hosts.byname; \
+               $(STDHOSTS) $(>) | \
+               $(AWK) 'BEGIN { OFS="\t"; } { print $$1, $$0 }' | \
+               $(MAKEDBM) - hosts.byaddr; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated hosts"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) hosts.byname; \
+                       $(YPPUSH) -d $(DOMAIN) hosts.byaddr; \
+                       $(ECHO) "pushed hosts"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+ethers.time: $(DIR)/ethers
+       -@if [ -f $(DIR)/ethers ]; then \
+               $(STDETHERS) $(>) | $(SED) -e s/#.*$$// | \
+               $(AWK) 'BEGIN { FS="\t"; OFS="\t"; } { print $$1, $$0 }' | \
+               $(MAKEDBM) - ethers.byaddr; \
+               $(STDETHERS) $(>) | \
+               $(AWK) 'BEGIN { FS="\t"; OFS="\t"; } { print $$2, $$0 }' | \
+               $(MAKEDBM) - ethers.byname; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated ethers"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) ethers.byaddr; \
+                       $(YPPUSH) -d $(DOMAIN) ethers.byname; \
+                       $(ECHO) "pushed ethers"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+networks.time: $(DIR)/networks
+       -@if [ -f $(>) ]; then \
+               $(SED) -e "/^#/d" -e s/#.*$$// $(>) | \
+               $(AWK) '{print $$1, $$0; for (i = 3;i <= NF;i++) print $$i,$$0}' | \
+               $(MAKEDBM) - networks.byname; \
+               $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \
+               $(MAKEDBM) - networks.byaddr; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated networks"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) networks.byname; \
+                       $(YPPUSH) -d $(DOMAIN) networks.byaddr; \
+                       $(ECHO) "pushed networks"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+rpc.time: $(DIR)/rpc
+       -@if [ -f $(>) ]; then \
+               $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \
+               $(MAKEDBM) - rpc.bynumber; \
+               $(SED) -e "/^#/d" -e s/#.*$$// $(>) | \
+               $(AWK) '{print $$1, $$0; for (i = 3;i <= NF;i++) print $$i,$$0}' | \
+               $(MAKEDBM) - rpc.byname; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated rpc"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) rpc.bynumber; \
+                       $(YPPUSH) -d $(DOMAIN) rpc.byname; \
+                       $(ECHO) "pushed rpc"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+
+services.time: $(DIR)/services
+       -@if [ -f $(>) ]; then \
+               $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \
+               $(MAKEDBM) - services.byname; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated services"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) services.byname; \
+                       $(ECHO) "pushed services"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+
+protocols.time: $(DIR)/protocols
+       -@if [ -f $(>) ]; then \
+               $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \
+               $(MAKEDBM) - protocols.bynumber; \
+               $(SED) -e "/^#/d" -e s/#.*$$// $(>) | \
+               $(AWK) '{print $$1, $$0; for (i = 3;i <= NF;i++) print $$i,$$0}' | \
+               $(MAKEDBM) - protocols.byname; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated protocols"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) protocols.bynumber; \
+                       $(YPPUSH) -d $(DOMAIN) protocols.byname; \
+                       $(ECHO) "pushed protocols"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+
+netid.time: $(DIR)/passwd $(DIR)/group $(DIR)/hosts $(DIR)/netid
+       -@$(MKNETID) -q -d $(DOMAIN) -p $(DIR)/passwd -g $(DIR)/group -h $(DIR)/hosts -m $(DIR)/netid | \
+         $(MAKEDBM) - netid.byname; \
+         $(TOUCH) $(@); \
+         $(ECHO) "updated netid"; \
+         if [ ! $(NOPUSH) ]; then \
+               $(YPPUSH) -d $(DOMAIN) netid.byname; \
+               $(ECHO) "pushed netid"; \
+         else \
+               : ; \
+         fi
+
+
+netgroup.time: $(DIR)/netgroup
+       -@if [ -f $(>) ]; then \
+               $(CAT) $(>) | $(MAKEDBM) - netgroup; \
+               $(CAT) $(>) | $(REVNETGROUP) -u -f - | \
+               $(MAKEDBM) - netgroup.byuser; \
+               $(CAT) $(>) | $(REVNETGROUP) -h -f - | \
+               $(MAKEDBM) - netgroup.byhost; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated netgroup"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) netgroup; \
+                       $(YPPUSH) -d $(DOMAIN) netgroup.byuser; \
+                       $(YPPUSH) -d $(DOMAIN) netgroup.byhost; \
+                       $(ECHO) "pushed netgroup"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+
+amd.home.time: $(AMDDIR)/amd.home
+       -@if [ -f $(>) ]; then \
+               $(SED) -e "s/#.*$$//" -e "/^$$/d" $(>) | \
+               $(AWK) '{ \
+                           for (i = 1; i <= NF; i++) \
+                               if (i == NF) { \
+                                   if (substr($$i, length($$i), 1) == "\\") { \
+                                       printf("%s", substr($$i, 1, length($$i) - 1)); \
+                                   } \
+                                   else \
+                                       printf("%s\n", $$i); \
+                               } \
+                               else \
+                                   printf("%s ", $$i); \
+                       }' | \
+               $(MAKEDBM) - amd.home; \
+               $(TOUCH) $(@); \
+               $(ECHO) "updated amd.home"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) amd.home; \
+                       $(ECHO) "pushed amd.home"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+
+aliases.time: $(DIR)/aliases
+       -@if [ -f $(>) ]; then \
+               $(CP) -p $(>) $(DOMAIN)-aliases; \
+               $(SENDMAIL) -bi -oA$(PWD)/$(DOMAIN)-aliases; \
+               $(MAKEDBM) -U $(DOMAIN)-aliases | $(MAKEDBM) - mail.aliases; \
+               $(MKALIAS) mail.aliases mail.byaddr; \
+               $(TOUCH) $(@); \
+               $(RM) $(DOMAIN)-aliases.db $(DOMAIN)-aliases; \
+               $(ECHO) "updated aliases"; \
+               if [ ! $(NOPUSH) ]; then \
+                       $(YPPUSH) -d $(DOMAIN) mail.aliases; \
+                       $(YPPUSH) -d $(DOMAIN) mail.byaddr; \
+                       $(ECHO) "pushed aliases"; \
+               else \
+                       : ; \
+               fi \
+       else \
+               $(ECHO) "couldn't find $(>)"; \
+       fi
+
+
+
+passwd: passwd.time
+group: group.time
+hosts: hosts.time
+ethers: ethers.time
+networks: networks.time
+rpc: rpc.time
+services: services.time
+protocols: protocols.time
+netid: netid.time
+netgroup: netgroup.time
+amd.home: amd.home.time
+aliases: aliases.time
+$(DIR)/passwd:
+$(DIR)/group:
+$(DIR)/hosts:
+$(DIR)/ethers:
+$(DIR)/networks:
+$(DIR)/rpc:
+$(DIR)/services:
+$(DIR)/protocols:
+$(DIR)/netid:
+$(DIR)/master.passwd:
+$(DIR)/netgroup:
+$(DIR)/aliases:
+$(AMDDIR)/amd.home:
diff --git a/ypinit.tproj/ypinit.sh b/ypinit.tproj/ypinit.sh
new file mode 100644 (file)
index 0000000..8c21e36
--- /dev/null
@@ -0,0 +1,402 @@
+#!/bin/sh
+#      $Id: ypinit.sh,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $
+#
+# ypinit.sh - setup an master or slave server.
+#
+DOMAINNAME=/bin/domainname
+HOSTNAME=/bin/hostname
+YPWHICH=/usr/bin/ypwhich
+YPXFR=/usr/sbin/ypxfr
+YP_DIR=/var/yp
+MAKEDBM=/usr/sbin/makedbm
+ERROR_EXISTS="NO"
+MAKE=make
+umask 077
+
+#set -xv
+
+ERROR=USAGE                            # assume usage error
+
+if [ $# -eq 1 ]
+then
+       if [ $1 = "-m" ]                # ypinit -m
+       then
+               DOMAIN=`${DOMAINNAME}`
+               SERVERTYPE=MASTER
+               ERROR=
+       fi
+
+       if [ $1 = "-u" ]                # ypinit -u
+       then
+               DOMAIN=`${DOMAINNAME}`
+               SERVERTYPE=UPDATE
+               ERROR=
+       fi
+fi
+
+if [ $# -eq 2 ]
+then
+       if [ $1 = "-m" ]                # ypinit -m domainname
+       then
+               DOMAIN=${2}
+               SERVERTYPE=MASTER
+               ERROR=
+       fi
+
+       if [ $1 = "-s" ]                # ypinit -s master_server
+       then
+               DOMAIN=`${DOMAINNAME}`
+               SERVERTYPE=SLAVE
+               MASTER=${2}
+               ERROR=
+       fi
+
+       if [ $1 = "-u" ]                # ypinit -u domainname
+       then
+               DOMAIN=${2}
+               SERVERTYPE=UPDATE
+               ERROR=
+       fi
+fi
+
+if [ $# -eq 3 ]
+then
+       if [ $1 = "-s" ]                # ypinit -s master_server domainname
+       then
+               DOMAIN=${3}
+               SERVERTYPE=SLAVE
+               MASTER=${2}
+               ERROR=
+       fi
+fi
+
+if [ "${ERROR}" = "USAGE" ]; then
+       cat << \__usage 1>&2
+usage: ypinit -m [domainname]
+       ypinit -s master_server [domainname]
+       ypinit -u [domainname]
+
+The `-m' flag builds a master YP server, and the `-s' flag builds
+a slave YP server.  When building a slave YP server, `master_server'
+must be an existing, reachable YP server.
+The `-u' is for updating the ypservers map on a master server.
+__usage
+
+       exit 1
+fi
+
+# Check if domainname is set, don't accept an empty domainname
+if [ -z "${DOMAIN}" ]; then
+       cat << \__no_domain 1>&2
+The local host's YP domain name has not been set.  Please set it with
+the domainname(8) command or pass the domain as an argument to ypinit(8).
+__no_domain
+
+       exit 1
+fi
+
+# Check if hostname is set, don't accept an empty hostname
+HOST=`${HOSTNAME}`
+if [ -z "${HOST}" ]; then
+       cat << \__no_hostname 1>&2
+The local host's hostname has not been set.  Please set it with the
+hostname(8) command.
+__no_hostname
+
+       exit 1
+fi
+
+# Check if we have contact with master.
+if [ "${SERVERTYPE}" = "SLAVE" ];
+then
+       COUNT=`${YPWHICH} -d ${DOMAIN} -m 2>/dev/null | grep -i ${MASTER} | wc -l | tr -d " "`
+       if [ "$COUNT" = "0" ]
+       then
+               echo "Can't enumerate maps from ${MASTER}. Please check that it is running." 1>&2
+               exit 1
+       fi
+fi
+
+# Check if user is root
+ID=`id -u`
+if [ "${ID}" != "0" ]; then
+       echo "You have to be the superuser to run this.  Please login as root." 1>&2
+       exit 1
+fi
+
+# Check if the YP directory exists.
+
+if [ ! -d ${YP_DIR} -o -f ${YP_DIR} ]
+then
+       echo "The directory ${YP_DIR} doesn't exist.  Restore it from the distribution." 1>&2
+       exit 1
+
+fi
+
+echo -n "Server Type: ${SERVERTYPE} Domain: ${DOMAIN}"
+if [ "${SERVERTYPE}" = "SLAVE" ]; then
+       echo -n " Master: ${MASTER}"
+fi
+echo ""
+
+if [ "${SERVERTYPE}" != "UPDATE" ];
+then
+       cat << \__notice1
+
+Creating an YP server will require that you answer a few questions.
+Questions will all be asked at the beginning of the procedure.
+
+__notice1
+
+       echo -n "Do you want this procedure to quit on non-fatal errors? [y/n: n]  "
+       read DOEXIT
+
+       case ${DOEXIT} in
+       y*|Y*)
+               ERROR_EXIT="YES"
+               ;;
+
+       *)      ERROR_EXIT="NO"
+               echo ""
+               echo "Ok, please remember to go back and redo manually whatever fails."
+               echo "If you don't, something might not work. "
+               ;;
+       esac
+
+       if [ -d "${YP_DIR}/${DOMAIN}" ]; then
+               echo "" 
+               echo -n "Can we destroy the existing ${YP_DIR}/${DOMAIN} and its contents? [y/n: n]  "
+               read KILL
+
+               ERROR=
+               case ${KILL} in
+               y*|Y*)
+                       ERROR="DELETE"
+                       ;;
+
+               *)      ERROR=
+                       ;;
+               esac
+
+               if [ "${ERROR}" = "DELETE" ]; then
+                       if ! rm -rf ${YP_DIR}/${DOMAIN}; then
+                               echo "Can't clean up old directory ${YP_DIR}/${DOMAIN}." 1>&2
+                               exit 1
+                       fi
+               else
+                       echo "OK, please clean it up by hand and start again.  Bye"
+                       exit 0
+               fi
+       
+       fi
+
+       if ! mkdir "${YP_DIR}/${DOMAIN}"; then
+               echo "Can't make new directory ${YP_DIR}/${DOMAIN}." 1>&2
+               exit 1
+       fi
+fi
+
+if [ "${SERVERTYPE}" = "MASTER" ];
+then
+
+       if [ ! -f ${YP_DIR}/Makefile ]
+       then
+               if [ ! -f ${YP_DIR}/Makefile.main ]
+               then
+                       echo "Can't find ${YP_DIR}/Makefile.main. " 1>&2
+                       exit 1
+               fi
+               cp ${YP_DIR}/Makefile.main ${YP_DIR}/Makefile
+       fi
+
+       SUBDIR=`grep "^SUBDIR=" ${YP_DIR}/Makefile`
+       
+       if [ -z "${SUBDIR}" ]
+       then
+               echo "Can't find line starting with 'SUBDIR=' in ${YP_DIR}/Makefile. " 1>&2
+               exit 1
+       fi
+
+       NEWSUBDIR="SUBDIR="
+       for DIR in `echo ${SUBDIR} | cut -c8-255`; do
+               if [ ${DIR} != ${DOMAIN} ]; then
+                       NEWSUBDIR="${NEWSUBDIR} ${DIR}"
+               fi
+       done
+       NEWSUBDIR="${NEWSUBDIR} ${DOMAIN}"
+
+       if [ -f ${YP_DIR}/Makefile.tmp ]; then 
+               rm ${YP_DIR}/Makefile.tmp
+       fi
+
+       mv ${YP_DIR}/Makefile ${YP_DIR}/Makefile.tmp
+       sed -e "s/^${SUBDIR}/${NEWSUBDIR}/" ${YP_DIR}/Makefile.tmp > \
+           ${YP_DIR}/Makefile
+       rm ${YP_DIR}/Makefile.tmp
+
+       if [ ! -f ${YP_DIR}/Makefile.yp ]; then
+               echo "Can't find ${YP_DIR}/Makefile.yp. " 1>&2
+               exit 1
+       fi
+
+       cp ${YP_DIR}/Makefile.yp ${YP_DIR}/${DOMAIN}/Makefile
+
+fi
+
+if [ "${SERVERTYPE}" = "SLAVE" ];
+then
+
+       echo "There will be no further questions. The remainder of the procedure"
+       echo "should take a few minutes, to copy the databases from ${MASTER}."
+
+       for MAP in `${YPWHICH} -d ${DOMAIN} -m | cut -d\  -f1`
+       do
+               echo "Transfering ${MAP}..."
+               if ! ${YPXFR} -h ${MASTER} -c -d ${DOMAIN} ${MAP}; then
+                       echo "Can't transfer map ${MAP}." 1>&2
+                       ERROR_EXISTS="YES"
+                       if [ "${ERROR_EXIT}" = "YES" ]; then
+                               exit 1
+                       fi
+               fi
+       done
+
+       echo ""
+       if [ "${ERROR_EXISTS}" = "YES"  ]; then
+               echo "${HOST} has been setup as an YP slave server with errors. " 1>&2
+               echo "Please remember fix any problem that occurred." 1>&2
+       else
+               echo "${HOST} has been setup as an YP slave server without any errors. "
+       fi
+
+       echo "Don't forget to update map ypservers on ${MASTER}."
+       exit 0
+fi
+
+LIST_OK="NO"
+
+while [ "${LIST_OK}" = "NO" ];
+do
+       
+       if [ "${SERVERTYPE}" = "MASTER" ];
+       then
+               HOST_LIST="${HOST}"
+               echo ""
+               echo "At this point, we have to construct a list of this domains YP servers."
+               echo "${HOST} is already known as master server."
+               echo "Please continue to add any slave servers, one per line. When you are"
+               echo "done with the list, type a <control D>."
+               echo "  master server   :  ${HOST}"
+       fi
+
+       if [ "${SERVERTYPE}" = "UPDATE" ];
+       then
+               HOST_LIST="${HOST}"
+               NEW_LIST=""
+               MASTER_NAME=""
+               SHORT_HOST=`echo ${HOST} | cut -d. -f1`
+               if [ -f ${YP_DIR}/${DOMAIN}/ypservers.db ];
+               then
+                       for srv in `${MAKEDBM} -u ${YP_DIR}/${DOMAIN}/ypservers | grep -v "^YP" | tr "\t" " " | cut -d\  -f1`;
+                       do
+                               short_srv=`echo ${srv} | cut -d. -f1`
+                               if [ "${SHORT_HOST}" != "${short_srv}" ]
+                               then
+                                       if [ "${NEW_LIST}" = "" ];
+                                       then
+                                               NEW_LIST="${srv}"
+                                       else
+                                               NEW_LIST="${NEW_LIST} ${srv}"
+                                       fi
+                               fi
+                       done;
+                       MASTER_NAME=`${MAKEDBM} -u ${YP_DIR}/${DOMAIN}/ypservers | grep "^YP_MASTER_NAME" | tr "\t" " " | cut -d\  -f2`
+               fi
+               echo ""
+               echo "Update the list of hosts running YP servers in domain ${DOMAIN}."
+               echo "Master for this domain is ${MASTER_NAME}."
+               echo ""
+               echo "First verify old servers, type \\ to remove a server." 
+               echo "Then add new servers, one per line. When done type a <control D>." 
+               echo ""
+               echo "  master server   :  ${HOST}"
+               if [ "${NEW_LIST}" != "" ]; then
+                       for node in $NEW_LIST; do
+                               echo -n "       verify host     : [${node}] "
+                               read verify
+                               if [ "${verify}" != "\\" ]; then
+                                       HOST_LIST="${HOST_LIST} ${node}"
+                               fi
+                       done;
+               fi
+       fi
+
+       echo -n "       next host to add:  "
+
+       while read h
+       do
+               echo -n "       next host to add:  "
+               HOST_LIST="${HOST_LIST} ${h}"
+       done
+
+       echo ""
+       echo "The current list of NIS servers looks like this:"
+       echo ""
+
+       for h in `echo ${HOST_LIST}`;
+       do
+               echo ${h}
+       done
+
+       echo ""
+       echo -n "Is this correct?  [y/n: y]  "
+       read hlist_ok
+
+       case $hlist_ok in
+       n*)     echo "Let's try the whole thing again...";;
+       N*)     echo "Let's try the whole thing again...";;
+       *)      LIST_OK="YES";;
+       esac
+
+done
+
+echo "Building ${YP_DIR}/${DOMAIN}/ypservers..."
+for host in ${HOST_LIST};
+do
+       echo "${host} ${host}"
+done | ${MAKEDBM} - ${YP_DIR}/${DOMAIN}/ypservers
+
+if [ $? -ne 0 ]; then
+       echo "" 1>&2
+       echo "Couldn't build yp data base ${YP_DIR}/${DOMAIN}/ypservers." 1>&2
+       ERROR_EXISTS="YES"
+       if [ "${ERROR_EXIT}" = "YES" ]; then 
+               exit 1
+       fi
+fi
+
+if [ "${SERVERTYPE}" = "MASTER" ]; then
+       
+       CUR_PWD=`pwd`
+       cd ${YP_DIR}/${DOMAIN}
+       echo "Running ${YP_DIR}/${DOMAIN}/Makefile..."
+       if ! ${MAKE} NOPUSH=1; then
+               echo "" 1>&2
+               echo "Error running Makefile." 1>&2
+               ERROR_EXISTS="YES"
+               if [ "${ERROR_EXIT}" = "YES" ]; then 
+                       exit 1
+               fi
+       fi
+
+       cd ${CUR_PWD}
+
+       echo ""
+       if [ "${ERROR_EXISTS}" = "YES" ]; then
+               echo "${HOST} has been setup as an YP master server with errors. " 1>&2
+               echo "Please remember fix any problem that occurred." 1>&2
+       else
+               echo "${HOST} has been setup as an YP master server without any errors. "
+       fi
+
+fi
diff --git a/ypmatch.tproj/Makefile b/ypmatch.tproj/Makefile
new file mode 100644 (file)
index 0000000..283ee4c
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ypmatch
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ypmatch.c
+
+OTHERSRCS = Makefile.dist Makefile.preamble ypmatch.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ypmatch.tproj/Makefile.dist b/ypmatch.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..fa9c3ba
--- /dev/null
@@ -0,0 +1,6 @@
+#      from: @(#)Makefile      5.8 (Berkeley) 7/28/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $
+
+PROG=  ypmatch
+
+.include <bsd.prog.mk>
diff --git a/ypmatch.tproj/Makefile.preamble b/ypmatch.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/ypmatch.tproj/PB.project b/ypmatch.tproj/PB.project
new file mode 100644 (file)
index 0000000..2b3516c
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (ypmatch.c); 
+        OTHER_SOURCES = (Makefile.dist, Makefile.preamble, ypmatch.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ypmatch; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ypmatch.tproj/ypmatch.1 b/ypmatch.tproj/ypmatch.1
new file mode 100644 (file)
index 0000000..f5e76ec
--- /dev/null
@@ -0,0 +1,71 @@
+.\" Copyright (c) 1993 Winning Strategies, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software developed by Winning Strategies, Inc.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\"    $Id: ypmatch.1,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $
+.\"
+.Dd December 3, 1993
+.Dt YPMATCH 1
+.Os
+.Sh NAME
+.Nm ypmatch
+.Nd "print the values of one or more keys in a YP database"
+.Sh SYNOPSIS
+.Nm ypmatch
+.Op Fl kt
+.Op Fl d Ar domainname
+.Ar key ...
+.Ar mapname
+.Nm ypmatch 
+.Fl x
+.Sh DESCRIPTION
+.Nm Ypmatch
+prints out the values of one or more keys from the 
+.Tn YP
+database specified by
+.Ar mapname,
+which may be a map name or a map nickname.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domainname
+Specify a domain other than the default domain.
+.It Fl k
+Display map keys.
+This option is useful with maps in which the values are null or the key
+is not part of the value.
+.It Fl t
+Inhibit translation of map nicknames
+to their corresponding map names.
+.It Fl x
+Display the map nickname table.
+.El
+.Sh SEE ALSO
+.Xr ypcat 1 ,
+.Xr yp 8
+.Sh AUTHOR
+Theo De Raadt
diff --git a/ypmatch.tproj/ypmatch.c b/ypmatch.tproj/ypmatch.c
new file mode 100644 (file)
index 0000000..5f78260
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$Id: ypmatch.c,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+struct ypalias {
+       char *alias, *name;
+} ypaliases[] = {
+       { "passwd", "passwd.byname" },
+       { "group", "group.byname" },
+       { "networks", "networks.byaddr" },
+       { "hosts", "hosts.byname" },
+       { "protocols", "protocols.bynumber" },
+       { "services", "services.byname" },
+       { "aliases", "mail.aliases" },
+       { "ethers", "ethers.byname" },
+};
+
+usage()
+{
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\typmatch [-d domain] [-t] [-k] key [key ...] mname\n");
+       fprintf(stderr, "\typmatch -x\n");
+       fprintf(stderr, "where\n");
+       fprintf(stderr, "\tmname may be either a mapname or a nickname for a map\n");
+       fprintf(stderr, "\t-t inhibits map nickname translation\n");
+       fprintf(stderr, "\t-k prints keys as well as values.\n");
+       fprintf(stderr, "\t-x dumps the map nickname translation table.\n");
+       exit(1);
+}
+
+int
+main(argc, argv)
+char **argv;
+{
+       char *domainname;
+       char *inkey, *inmap, *outbuf;
+       extern char *optarg;
+       extern int optind;
+       int outbuflen, key, notrans;
+       int c, r, i;
+
+       notrans = key = 0;
+       yp_get_default_domain(&domainname);
+
+       while( (c=getopt(argc, argv, "xd:kt")) != -1)
+               switch(c) {
+               case 'x':
+                       for(i=0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+                               printf("Use \"%s\" for \"%s\"\n",
+                                       ypaliases[i].alias,
+                                       ypaliases[i].name);
+                       exit(0);
+               case 'd':
+                       domainname = optarg;
+                       break;
+               case 't':
+                       notrans++;
+                       break;
+               case 'k':
+                       key++;
+                       break;
+               default:
+                       usage();
+               }
+
+       if( (argc-optind) < 2 )
+               usage();
+
+       inmap = argv[argc-1];
+       for(i=0; (!notrans) && i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+               if( strcmp(inmap, ypaliases[i].alias) == 0)
+                       inmap = ypaliases[i].name;
+       for(; optind < argc-1; optind++) {
+               inkey = argv[optind];
+
+               r = yp_match(domainname, inmap, inkey,
+                       strlen(inkey), &outbuf, &outbuflen);
+               switch(r) {
+               case 0:
+                       if(key)
+                               printf("%s ", inkey);
+                       printf("%*.*s\n", outbuflen, outbuflen, outbuf);
+                       break;
+               case YPERR_YPBIND:
+                       fprintf(stderr, "yp_match: not running ypbind\n");
+                       exit(1);
+               default:
+                       fprintf(stderr, "Can't match key %s in map %s. Reason: %s\n",
+                               inkey, inmap, yperr_string(r));
+                       break;
+               }
+       }
+       exit(0);
+}
diff --git a/yppoll.tproj/Makefile b/yppoll.tproj/Makefile
new file mode 100644 (file)
index 0000000..38f2ae4
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = yppoll
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = yppoll.c
+
+OTHERSRCS = Makefile.dist Makefile.preamble yppoll.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/yppoll.tproj/Makefile.dist b/yppoll.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..2274b91
--- /dev/null
@@ -0,0 +1,7 @@
+#      from: @(#)Makefile      5.8 (Berkeley) 7/28/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $
+
+PROG=  yppoll
+MAN8=  yppoll.0
+
+.include <bsd.prog.mk>
diff --git a/yppoll.tproj/Makefile.preamble b/yppoll.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/yppoll.tproj/PB.project b/yppoll.tproj/PB.project
new file mode 100644 (file)
index 0000000..d763e38
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (yppoll.c); 
+        OTHER_SOURCES = (Makefile.dist, Makefile.preamble, yppoll.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = yppoll; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/yppoll.tproj/yppoll.8 b/yppoll.tproj/yppoll.8
new file mode 100644 (file)
index 0000000..db17f7b
--- /dev/null
@@ -0,0 +1,63 @@
+.\" Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote
+.\"    products derived from this software without specific prior written
+.\"    permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    $Id: yppoll.8,v 1.1.1.1 1999/05/02 03:59:03 wsanchez Exp $
+.\"
+.Dd August 18, 1994
+.Dt YPPOLL 8
+.Os NetBSD
+.Sh NAME
+.Nm yppoll
+.Nd get version of a YP map from YP server
+.Sh SYNOPSIS
+.Nm yppoll
+.Op Fl h Ar host
+.Op Fl d Ar domainname
+.Ar mapname
+.Sh DESCRIPTION
+.Nm yppoll 
+is used to get information of a maps order number and master server.
+This utility is useful when determining if different servers have the
+same version of a map.
+.Nm yppoll
+normally talks with the default
+.Xr ypserv 8
+process, but by using the 
+.Fl h
+option it is possible to talk with a specific server.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domain
+Don't use default domain, use the specified domain.
+.It Fl h Ar host
+Get map information from host instead of the default YP server.
+.El
+.Sh SEE ALSO
+.Xr ypserv 8 
+.Sh AUTHOR
+Theo de Raadt, John Brezak and Mats O Jansson
diff --git a/yppoll.tproj/yppoll.c b/yppoll.tproj/yppoll.c
new file mode 100644 (file)
index 0000000..5f1ddc5
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
+ * Copyright (c) 1992, 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt and
+ *     John Brezak.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: yppoll.c,v 1.1.1.1 1999/05/02 03:59:03 wsanchez Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <time.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+void
+usage()
+{
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\typpoll [-h host] [-d domainname] mapname\n");
+       exit(1);
+}
+
+int
+get_remote_info(indomain, inmap, server, outorder, outname)
+       char *indomain;
+       char *inmap;
+       char *server;
+       int *outorder;
+       char **outname;
+{
+       struct ypresp_order ypro;
+       struct ypresp_master yprm;
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       int r;
+       struct sockaddr_in rsrv_sin;
+       int rsrv_sock;
+       CLIENT *client;
+       struct hostent *h;
+
+       bzero((char *)&rsrv_sin, sizeof rsrv_sin);
+       rsrv_sin.sin_len = sizeof rsrv_sin;
+       rsrv_sin.sin_family = AF_INET;
+       rsrv_sock = RPC_ANYSOCK;
+
+       h = gethostbyname(server);
+       if (h == NULL) {
+               if (inet_aton(server, &rsrv_sin.sin_addr) == 0) {
+                       fprintf(stderr, "unknown host %s\n", server);
+                       exit(1);
+               }
+       } else {
+               rsrv_sin.sin_addr.s_addr = *(u_long *)h->h_addr;
+       }
+
+       tv.tv_sec = 10;
+       tv.tv_usec = 0;
+
+       client = clntudp_create(&rsrv_sin, YPPROG, YPVERS, tv, &rsrv_sock);
+       if (client == NULL) {
+               fprintf(stderr, "clntudp_create: no contact with host %s.\n",
+                   server);
+               exit(1);
+       }
+       
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+
+       bzero((char *)(char *)&ypro, sizeof ypro);
+
+       r = clnt_call(client, YPPROC_ORDER, xdr_ypreq_nokey, &yprnk,
+           xdr_ypresp_order, &ypro, tv);
+       if (r != RPC_SUCCESS)
+               clnt_perror(client, "yp_order: clnt_call");
+
+       *outorder = ypro.ordernum;
+       xdr_free(xdr_ypresp_order, (char *)&ypro);
+
+       r = ypprot_err(ypro.status);
+       if (r == RPC_SUCCESS) {
+               bzero((char *)&yprm, sizeof yprm);
+
+               r = clnt_call(client, YPPROC_MASTER, xdr_ypreq_nokey,
+                   &yprnk, xdr_ypresp_master, &yprm, tv);
+               if (r != RPC_SUCCESS)
+                       clnt_perror(client, "yp_master: clnt_call");
+               r = ypprot_err(yprm.status);
+               if (r==0)
+                       *outname = (char *)strdup(yprm.master);
+               xdr_free(xdr_ypresp_master, (char *)&yprm);
+       }
+       clnt_destroy(client);
+       return r;
+}
+
+int
+main(argc, argv)
+       int  argc;
+       char **argv;
+{
+       char *domainname;
+       char *hostname = NULL;
+       char *inmap, *master;
+       int order;
+       extern char *optarg;
+       extern int optind;
+       int c, r;
+
+       yp_get_default_domain(&domainname);
+
+       while ((c=getopt(argc, argv, "h:d:?")) != -1)
+               switch (c) {
+               case 'd':
+                       domainname = optarg;
+                       break;
+               case 'h':
+                       hostname = optarg;
+                       break;
+               default:
+                       usage();
+                       /*NOTREACHED*/
+               }
+
+       if (optind + 1 != argc )
+               usage();
+       inmap = argv[optind];
+
+       if (hostname != NULL) {
+               r = get_remote_info(domainname, inmap, hostname,
+                   &order, &master);
+       } else {
+               r = yp_order(domainname, inmap, &order);
+               if (r == 0)
+                       r = yp_master(domainname, inmap, &master);
+       }
+
+       if (r != 0) {
+               fprintf(stderr, "No such map %s. Reason: %s\n",
+                   inmap, yperr_string(r));
+               exit(1);
+       }
+
+       printf("Map %s has order number %d. %s", inmap, order,
+           ctime((time_t *)&order));
+       printf("The master server is %s.\n", master);
+       exit(0);
+}
diff --git a/yppush.tproj/Makefile b/yppush.tproj/Makefile
new file mode 100644 (file)
index 0000000..ed8971f
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = yppush
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = yppush.h ypdb.h yplib_host.h ypdef.h
+
+CFILES = ypdb.c yplib_host.c yppush.c yppush_err.c yppush_proc.c\
+         yppush_svc.c yppush_xdr.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble yppush.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/yppush.tproj/Makefile.postamble b/yppush.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/yppush.tproj/Makefile.preamble b/yppush.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/yppush.tproj/PB.project b/yppush.tproj/PB.project
new file mode 100644 (file)
index 0000000..f91db95
--- /dev/null
@@ -0,0 +1,35 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (yppush.h, ypdb.h, yplib_host.h, ypdef.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (
+            ypdb.c, 
+            yplib_host.c, 
+            yppush.c, 
+            yppush_err.c, 
+            yppush_proc.c, 
+            yppush_svc.c, 
+            yppush_xdr.c
+        ); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, yppush.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = yppush; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/yppush.tproj/ypdb.c b/yppush.tproj/ypdb.c
new file mode 100644 (file)
index 0000000..c9bd178
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ypdb.h"
+
+#ifdef YPDB_PATCH
+extern DBM *__hash_open();
+#else
+extern DBM *__bt_open();
+#endif
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+       char path[MAXPATHLEN];
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       char path[MAXPATHLEN];
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       db = (DBM *)__bt_open(path, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open_suf(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       return ((DBM *)__hash_open(file, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       db = (DBM *)__bt_open(file, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+extern void
+ypdb_close(db)
+       DBM *db;
+{
+       (void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_fetch(db, key)
+       DBM *db;
+       datum key;
+{
+       datum retval;
+       int status;
+
+       status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+       if (status) {
+               retval.dptr = NULL;
+               retval.dsize = 0;
+       }
+       return (retval);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_firstkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_nextkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_setkey(db, key)
+       DBM *db;
+        datum key;
+{
+       int status;
+       datum retdata;
+#ifdef YPDB_PATCH
+       datum retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       while ((retkey.dptr != NULL) &&
+              ((retkey.dsize != key.dsize) ||
+               (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) {
+         status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+         if (status)
+               retkey.dptr = NULL;
+       };
+       return (retkey);
+#else
+       status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR);
+       if (status)
+               key.dptr = NULL;
+       return (key);
+#endif
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ */
+
+int
+ypdb_delete(db, key)
+       DBM *db;
+       datum key;
+{
+       int status;
+
+       status = (db->del)(db, (DBT *)&key, 0);
+       if (status)
+               return (-1);
+       else
+               return (0);
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ *      1 if YPDB_INSERT and entry exists
+ */
+
+int
+ypdb_store(db, key, content, flags)
+       DBM *db;
+       datum key, content;
+       int flags;
+{
+       return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+           (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0));
+}
+
diff --git a/yppush.tproj/ypdb.h b/yppush.tproj/ypdb.h
new file mode 100644 (file)
index 0000000..9afbad5
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDB_H_
+#define _YPDB_H_
+
+#ifndef _DB_H_
+#include <bsd/db.h>
+#endif
+
+#define YPDB_SUFFIX    ".db"
+
+/* Flags to ypdb_store(). */
+#define YPDB_INSERT      0
+#define YPDB_REPLACE     1
+
+#ifndef DATUM
+typedef struct {
+       char    *dptr;
+       int     dsize;
+} datum;
+#define DATUM
+#endif
+
+typedef DB DBM;
+
+__BEGIN_DECLS
+void    ypdb_close __P((DBM *));
+datum   ypdb_fetch __P((DBM *, datum));
+datum   ypdb_firstkey __P((DBM *));
+datum   ypdb_nextkey __P((DBM *));
+datum   ypdb_setkey __P((DBM *, datum));
+DBM     *ypdb_open __P((const char *, int, int));
+DBM     *ypdb_open_suf __P((const char *, int, int));
+int     ypdb_store __P((DBM *, datum, datum, int));
+__END_DECLS
+
+#endif /* !_YPDB_H_ */
diff --git a/yppush.tproj/ypdef.h b/yppush.tproj/ypdef.h
new file mode 100644 (file)
index 0000000..89970d7
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDEF_H_
+#define _YPDEF_H_
+
+#define YP_DB_PATH "/var/yp"
+#define YP_LAST_KEY        "YP_LAST_MODIFIED"
+#define YP_LAST_LEN       (sizeof(YP_LAST_KEY)-1)
+#define YP_INPUT_KEY       "YP_INPUT_FILE"
+#define YP_INPUT_LEN      (sizeof(YP_INPUT_KEY)-1)
+#define YP_OUTPUT_KEY      "YP_OUTPUT_FILE"
+#define YP_OUTPUT_LEN     (sizeof(YP_OUTPUT_KEY)-1)
+#define YP_MASTER_KEY      "YP_MASTER_NAME"
+#define YP_MASTER_LEN     (sizeof(YP_MASTER_KEY)-1)
+#define YP_DOMAIN_KEY      "YP_DOMAIN_NAME"
+#define YP_DOMAIN_LEN     (sizeof(YP_DOMAIN_KEY)-1)
+#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN"
+#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1)
+#define YP_SECURE_KEY      "YP_SECURE"
+#define YP_SECURE_LEN      (sizeof(YP_SECURE_KEY)-1)
+
+#define MAX_LAST_LEN 10
+#define MAX_MASTER_LEN 255
+#define YP_HOSTNAME "hosts.byname"
+#define YP_HOSTADDR "hosts.byaddr"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define YPXFR_PROC "/usr/sbin/ypxfr"
+#define YPPUSH_PROC "/usr/sbin/yppush"
+#define YPSERV_PID_PATH "/var/run/ypserv.pid"
+#define YP_SECURENET_FILE "/var/yp/securenet"
+
+#endif /* !_YPDEF_H_ */
diff --git a/yppush.tproj/yplib_host.c b/yppush.tproj/yplib_host.c
new file mode 100644 (file)
index 0000000..70b914b
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char *rcsid = "$OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+extern bool_t xdr_domainname(), xdr_ypbind_resp();
+extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
+extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val();
+extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq();
+extern bool_t xdr_ypresp_master();
+
+extern int (*ypresp_allfn)();
+extern void *ypresp_data;
+
+int _yplib_host_timeout = 10;
+
+CLIENT *
+yp_bind_host(server,program,version,port,usetcp)
+char *server;
+u_long program,version;
+u_short port;
+int usetcp;
+{
+       struct sockaddr_in rsrv_sin;
+       int rsrv_sock;
+       struct hostent *h;
+       struct timeval tv;
+       static CLIENT *client;
+
+       memset(&rsrv_sin, 0, sizeof rsrv_sin);
+       rsrv_sin.sin_len = sizeof rsrv_sin;
+       rsrv_sin.sin_family = AF_INET;
+       rsrv_sock = RPC_ANYSOCK;
+       if (port != 0) {
+               rsrv_sin.sin_port = htons(port);
+       }
+
+       if ((*server >= '0') && (*server <= '9')) {
+               if(inet_aton(server,&rsrv_sin.sin_addr) == 0) {
+                       fprintf(stderr, "inet_aton: invalid address %s.\n",
+                               server);
+                       exit(1);
+               }
+       } else {
+               h = gethostbyname(server);
+               if(h == NULL) {
+                       fprintf(stderr, "gethostbyname: unknown host %s.\n",
+                               server);
+                       exit(1);
+               }
+               rsrv_sin.sin_addr.s_addr = *(u_int32_t *)h->h_addr;
+       }
+
+       tv.tv_sec = 10;
+       tv.tv_usec = 0;
+
+       if (usetcp) {
+               client = clnttcp_create(&rsrv_sin, program, version,
+                                       &rsrv_sock, 0, 0);
+       } else {
+               client = clntudp_create(&rsrv_sin, program, version, tv,
+                                       &rsrv_sock);
+       }
+
+       if (client == NULL) {
+               fprintf(stderr, "clntudp_create: no contact with host %s.\n",
+                       server);
+               exit(1);
+       }
+
+       return(client);
+       
+}
+
+CLIENT *
+yp_bind_local(program,version)
+u_long program,version;
+{
+       struct sockaddr_in rsrv_sin;
+       int rsrv_sock;
+       struct timeval tv;
+       static CLIENT *client;
+
+       memset(&rsrv_sin, 0, sizeof rsrv_sin);
+       rsrv_sin.sin_len = sizeof rsrv_sin;
+       rsrv_sin.sin_family = AF_INET;
+       rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       rsrv_sock = RPC_ANYSOCK;
+
+       tv.tv_sec = 10;
+       tv.tv_usec = 0;
+
+       client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock);
+       if (client == NULL) {
+               fprintf(stderr,"clntudp_create: no contact with localhost.\n");
+               exit(1);
+       }
+
+       return(client);
+       
+}
+
+int
+yp_match_host(client, indomain, inmap, inkey, inkeylen, outval, outvallen)
+CLIENT *client;
+char *indomain;
+char *inmap;
+const char *inkey;
+int inkeylen;
+char **outval;
+int *outvallen;
+{
+       struct ypresp_val yprv;
+       struct timeval tv;
+       struct ypreq_key yprk;
+       int r;
+
+       *outval = NULL;
+       *outvallen = 0;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprk.domain = indomain;
+       yprk.map = inmap;
+       yprk.key.keydat_val = (char *)inkey;
+       yprk.key.keydat_len = inkeylen;
+
+       memset(&yprv, 0, sizeof yprv);
+
+       r = clnt_call(client, YPPROC_MATCH,
+               xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_match_host: clnt_call");
+       }
+       if( !(r=ypprot_err(yprv.stat)) ) {
+               *outvallen = yprv.val.valdat_len;
+               *outval = (char *)malloc(*outvallen+1);
+               memcpy(*outval, yprv.val.valdat_val, *outvallen);
+               (*outval)[*outvallen] = '\0';
+       }
+       xdr_free(xdr_ypresp_val, (char *)&yprv);
+       return r;
+}
+
+int
+yp_first_host(client, indomain, inmap, outkey, outkeylen, outval, outvallen)
+CLIENT *client;
+char *indomain;
+char *inmap;
+char **outkey;
+int *outkeylen;
+char **outval;
+int *outvallen;
+{
+       struct ypresp_key_val yprkv;
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       int r;
+
+       *outkey = *outval = NULL;
+       *outkeylen = *outvallen = 0;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+       memset(&yprkv, 0, sizeof yprkv);
+
+       r = clnt_call(client, YPPROC_FIRST,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_first_host: clnt_call");
+       }
+       if( !(r=ypprot_err(yprkv.stat)) ) {
+               *outkeylen = yprkv.key.keydat_len;
+               *outkey = (char *)malloc(*outkeylen+1);
+               memcpy(*outkey, yprkv.key.keydat_val, *outkeylen);
+               (*outkey)[*outkeylen] = '\0';
+               *outvallen = yprkv.val.valdat_len;
+               *outval = (char *)malloc(*outvallen+1);
+               memcpy(*outval, yprkv.val.valdat_val, *outvallen);
+               (*outval)[*outvallen] = '\0';
+       }
+       xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
+       return r;
+}
+
+int
+yp_next_host(client, indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen)
+CLIENT *client;
+char *indomain;
+char *inmap;
+char *inkey;
+int inkeylen;
+char **outkey;
+int *outkeylen;
+char **outval;
+int *outvallen;
+{
+       struct ypresp_key_val yprkv;
+       struct ypreq_key yprk;
+       struct timeval tv;
+       int r;
+
+       *outkey = *outval = NULL;
+       *outkeylen = *outvallen = 0;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprk.domain = indomain;
+       yprk.map = inmap;
+       yprk.key.keydat_val = inkey;
+       yprk.key.keydat_len = inkeylen;
+       memset(&yprkv, 0, sizeof yprkv);
+
+       r = clnt_call(client, YPPROC_NEXT,
+               xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_next_host: clnt_call");
+       }
+       if( !(r=ypprot_err(yprkv.stat)) ) {
+               *outkeylen = yprkv.key.keydat_len;
+               *outkey = (char *)malloc(*outkeylen+1);
+               memcpy(*outkey, yprkv.key.keydat_val, *outkeylen);
+               (*outkey)[*outkeylen] = '\0';
+               *outvallen = yprkv.val.valdat_len;
+               *outval = (char *)malloc(*outvallen+1);
+               memcpy(*outval, yprkv.val.valdat_val, *outvallen);
+               (*outval)[*outvallen] = '\0';
+       }
+       xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
+       return r;
+}
+
+int
+yp_all_host(client, indomain, inmap, incallback)
+CLIENT *client;
+char *indomain;
+char *inmap;
+struct ypall_callback *incallback;
+{
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       u_long status;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+       ypresp_allfn = incallback->foreach;
+       ypresp_data = (void *)incallback->data;
+
+       (void) clnt_call(client, YPPROC_ALL,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv);
+       xdr_free(xdr_ypresp_all_seq, (char *)&status);  /* not really needed... */
+
+       if(status != YP_FALSE)
+               return ypprot_err(status);
+       return 0;
+}
+
+int
+yp_order_host(client, indomain, inmap, outorder)
+CLIENT *client;
+char *indomain;
+char *inmap;
+u_int32_t *outorder;
+{
+       struct ypresp_order ypro;
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       int r;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+
+       memset(&ypro, 0, sizeof ypro);
+
+       r = clnt_call(client, YPPROC_ORDER,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_order_host: clnt_call");
+       }
+
+       *outorder = ypro.ordernum;
+       xdr_free(xdr_ypresp_order, (char *)&ypro);
+       return ypprot_err(ypro.stat);
+}
+
+int
+yp_master_host(client, indomain, inmap, outname)
+CLIENT *client;
+char *indomain;
+char *inmap;
+char **outname;
+{
+       struct ypresp_master yprm;
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       int r;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+
+       memset(&yprm, 0, sizeof yprm);
+
+       r = clnt_call(client, YPPROC_MASTER,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_master: clnt_call");
+       }
+       if( !(r=ypprot_err(yprm.stat)) ) {
+               *outname = (char *)strdup(yprm.peer);
+       }
+       xdr_free(xdr_ypresp_master, (char *)&yprm);
+       return r;
+}
+
+int
+yp_maplist_host(client, indomain, outmaplist)
+CLIENT *client;
+char *indomain;
+struct ypmaplist **outmaplist;
+{
+       struct ypresp_maplist ypml;
+       struct timeval tv;
+       int r;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       memset(&ypml, 0, sizeof ypml);
+
+       r = clnt_call(client, YPPROC_MAPLIST,
+               xdr_domainname, &indomain, xdr_ypresp_maplist, &ypml, tv);
+       if (r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_maplist: clnt_call");
+       }
+       *outmaplist = ypml.maps;
+       /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/
+       return ypprot_err(ypml.stat);
+}
+
diff --git a/yppush.tproj/yplib_host.h b/yppush.tproj/yplib_host.h
new file mode 100644 (file)
index 0000000..038fb68
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplib_host.h,v 1.4 1997/05/01 22:14:45 niklas Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPLIB_HOST_H_
+#define _YPLIB_HOST_H_
+
+int    yp_match_host   __P((CLIENT *client, char *indomain, char *inmap,
+                           const char *inkey, int inkeylen, char **outval,
+                           int *outvallen));
+int    yp_first_host   __P((CLIENT *client, char *indomain, char *inmap,
+                           char **outkey, int *outkeylen, char **outval,
+                           int *outvallen));
+int    yp_next_host    __P((CLIENT *client, char *indomain, char *inmap,
+                           char *inkey, int inkeylen, char **outkey,
+                           int *outkeylen, char **outval, int *outvallen));
+int    yp_master_host  __P((CLIENT *client,
+                           char *indomain, char *inmap, char **outname));
+int    yp_order_host   __P((CLIENT *client,
+                           char *indomain, char *inmap, u_int32_t *outorder));
+int    yp_all_host     __P((CLIENT *client, char *indomain, char *inmap,
+                           struct ypall_callback *incallback));
+int    yp_maplist_host __P((CLIENT *client, char *indomain,
+                           struct ypmaplist **outmaplist));
+CLIENT *yp_bind_local  __P((u_long program, u_long version));
+CLIENT *yp_bind_host   __P((char *server, u_long program, u_long version,
+                           u_short port, int usetcp));
+
+#endif /* _YPLIB_HOST_H_ */
+
diff --git a/yppush.tproj/yppush.8 b/yppush.tproj/yppush.8
new file mode 100644 (file)
index 0000000..2777199
--- /dev/null
@@ -0,0 +1,68 @@
+.\"    $OpenBSD: yppush.8,v 1.4 1997/05/01 21:08:49 niklas Exp $
+.\" Copyright (c) 1995 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd January 29, 1995
+.Dt YPPUSH 8
+.Os
+.Sh NAME
+.Nm yppush
+.Nd force distribution of YP map
+.Sh SYNOPSIS
+.Nm yppush
+.Op Fl d Ar domainname
+.Op Fl h Ar hostname
+.\" .Op Fl p Ar paralleljobs
+.\" .Op Fl t Ar timeout
+.Op Fl v
+.Ar mapname
+.Sh DESCRIPTION
+.Nm yppush
+is used to distribute an YP map from a master server to any
+slave server in the domain. All servers of the domain is fetched from the YP
+map ypservers.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domainname
+Don't use default domain, use the specified domain.
+.It Fl h Ar hostname
+Distribute map only to one host and not to the hosts in the ypserver map.
+.\" .It Fl p Ar paralleljobs
+.\"Set the number of parallel transfers.
+.\".It Fl t Ar timeout
+.\"Set the amount of time to elapse before a timeout is registered.
+.It Fl v
+Verbose. Announce what the program is doing.
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr ypserv 8 
+.Sh AUTHOR
+Mats O Jansson
diff --git a/yppush.tproj/yppush.c b/yppush.tproj/yppush.c
new file mode 100644 (file)
index 0000000..5ddd82c
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppush.c,v 1.10 1997/11/10 05:49:17 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1995 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$OpenBSD: yppush.c,v 1.10 1997/11/10 05:49:17 deraadt Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/signal.h>
+#include <sys/wait.h>
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "yplib_host.h"
+#include "ypdef.h"
+#include "ypdb.h"
+
+int  Verbose = 0;
+char Domain[MAXHOSTNAMELEN], Map[255];
+u_int32_t OrderNum;
+char *master;
+
+extern void yppush_xfrrespprog_1(struct svc_req *request, SVCXPRT *xprt);
+extern bool_t xdr_ypreq_xfr(XDR *, struct ypreq_xfr *);
+
+void
+usage()
+{
+       fprintf(stderr, "Usage:\n");
+/*
+       fprintf(stderr, "\typpush [-d domainname] [-t seconds] [-p #paralleljobs] [-h host] [-v] mapname\n");
+*/
+       fprintf(stderr, "\typpush [-d domainname] [-h host] [-v] mapname\n");
+       exit(1);
+}
+
+void
+_svc_run()
+{
+       fd_set readfds;
+       struct timeval timeout;
+
+       timeout.tv_sec=60; timeout.tv_usec=0;
+
+       for(;;) {
+               readfds = svc_fdset;
+               switch (select(_rpc_dtablesize(), &readfds, (void *) 0,
+                              (void *) 0, &timeout)) {
+               case -1:
+                       if (errno == EINTR) {
+                               continue;
+                       }
+                       perror("yppush: _svc_run: select failed");
+                       return;
+               case 0:
+                       fprintf(stderr, "yppush: Callback timed out.\n");
+                       exit(0);
+               default:
+                       svc_getreqset(&readfds);
+               }
+       }
+       
+}
+
+void
+req_xfr(pid, prog, transp, host, client)
+pid_t pid;
+u_int prog;
+SVCXPRT *transp;
+char *host;
+CLIENT *client;
+{
+       struct ypreq_xfr request;
+       struct timeval tv;
+
+       tv.tv_sec=0; tv.tv_usec=0;
+
+       request.map_parms.domain=(char *)&Domain;
+       request.map_parms.map=(char *)&Map;
+       request.map_parms.peer=master;
+       request.map_parms.ordernum=OrderNum;
+       request.transid=(u_int)pid;
+       request.prog=prog;
+       request.port=transp->xp_port;
+
+       if (Verbose)
+               printf("%d: %s(%u@%s) -> %s@%s\n",
+                      request.transid,
+                      request.map_parms.map,
+                      request.map_parms.ordernum,
+                      host,
+                      request.map_parms.peer,
+                      request.map_parms.domain);
+       switch (clnt_call(client, YPPROC_XFR, xdr_ypreq_xfr, &request,
+                         xdr_void, NULL, tv)) {
+       case RPC_SUCCESS:
+       case RPC_TIMEDOUT:
+               break;
+       default:
+               clnt_perror(client, "yppush: Cannot call YPPROC_XFR");
+               kill(pid, SIGTERM);
+       }
+}
+
+void
+push(inlen, indata)
+int inlen;
+char *indata;
+{
+       char host[MAXHOSTNAMELEN];
+       CLIENT *client;
+       SVCXPRT *transp;
+       int sock = RPC_ANYSOCK;
+       u_int prog;
+       bool_t sts;
+       pid_t pid;
+       int status;
+       struct rusage res;
+
+       snprintf(host,sizeof host,"%*.*s" ,inlen ,inlen, indata);
+
+       client = clnt_create(host, YPPROG, YPVERS, "tcp");
+       if (client == NULL) {
+               if (Verbose)
+                       fprintf(stderr,"Target Host: %s\n",host);
+               clnt_pcreateerror("yppush: Cannot create client");
+               return;
+       }
+
+       transp = svcudp_create(sock);
+       if (transp == NULL) {
+               fprintf(stderr, "yppush: Cannot create callback transport.\n");
+               return;
+       }
+       if (transp->xp_port >= IPPORT_RESERVED) {
+               SVC_DESTROY(transp);
+               fprintf(stderr, "yppush: Cannot allocate reserved port.\n");
+               return;
+       }
+
+       for (prog=0x40000000; prog<0x5fffffff; prog++) {
+               if (sts = svc_register(transp, prog, 1,
+                   yppush_xfrrespprog_1, IPPROTO_UDP))
+                       break;
+       }
+
+       if (!sts) {
+               fprintf(stderr, "yppush: Cannot register callback.\n");
+               return;
+       }
+
+       switch(pid=fork()) {
+       case -1:
+               fprintf(stderr, "yppush: Cannot fork.\n");
+               exit(1);
+       case 0:
+               _svc_run();
+               exit(0);
+       default:
+               close(transp->xp_sock);
+               transp->xp_sock = -1;
+               req_xfr(pid, prog, transp, host, client);
+               wait4(pid, &status, 0, &res);
+               svc_unregister(prog, 1);
+               if (client != NULL)
+                       clnt_destroy(client);
+               /* XXX transp leak? */
+       }
+
+}
+
+int
+pushit(instatus, inkey, inkeylen, inval, invallen, indata)
+int instatus;
+char *inkey;
+int inkeylen;
+char *inval;
+int invallen;
+char *indata;
+{
+       if(instatus != YP_TRUE)
+               return instatus;
+       push(invallen, inval);
+       return 0;
+}
+
+int
+main(argc, argv)
+int  argc;
+char **argv;
+{
+       struct ypall_callback ypcb;
+       extern char *optarg;
+       extern int optind;
+       char    *domain,*map,*hostname,*parallel,*timeout;
+       int c, r, i;
+       char *ypmap = "ypservers";
+       CLIENT *client;
+       static char map_path[MAXPATHLEN];
+       struct stat finfo;
+       DBM *yp_databas;
+       char order_key[YP_LAST_LEN] = YP_LAST_KEY;
+       datum o;
+
+        yp_get_default_domain(&domain);
+       hostname = NULL;
+/*
+       while( (c=getopt(argc, argv, "d:h:p:t:v?")) != -1)
+*/
+       while( (c=getopt(argc, argv, "d:h:v?")) != -1)
+               switch(c) {
+               case 'd':
+                        domain = optarg;
+                       break;
+               case 'h':
+                       hostname = optarg;
+                       break;
+               case 'p':
+                       parallel = optarg;
+                       break;
+               case 't':
+                       timeout = optarg;
+                       break;
+                case 'v':
+                        Verbose = 1;
+                        break;
+                case '?':
+                        usage();
+                        /*NOTREACHED*/
+               }
+
+       if(optind + 1 != argc )
+               usage();
+
+       map = argv[optind];
+
+       strncpy(Domain,domain,sizeof(Domain)-1);
+       Domain[sizeof(Domain)-1] = '\0';
+       strncpy(Map,map,sizeof(Map)-1);
+       Map[sizeof(Map)-1] = '\0';
+
+       /* Check domain */
+       snprintf(map_path,sizeof map_path,"%s/%s",YP_DB_PATH,domain);
+       if (!((stat(map_path, &finfo) == 0) &&
+             ((finfo.st_mode & S_IFMT) == S_IFDIR))) {
+               fprintf(stderr,"yppush: Map does not exist.\n");
+               exit(1);
+       }
+               
+       
+       /* Check map */
+       snprintf(map_path,sizeof map_path,"%s/%s/%s%s",
+           YP_DB_PATH,domain,Map,YPDB_SUFFIX);
+       if (!(stat(map_path, &finfo) == 0)) {
+               fprintf(stderr,"yppush: Map does not exist.\n");
+               exit(1);
+       }
+               
+       snprintf(map_path,sizeof map_path,"%s/%s/%s",YP_DB_PATH,domain,Map);
+       yp_databas = ypdb_open(map_path,0,O_RDONLY);
+       OrderNum=0xffffffff;
+       if (yp_databas == 0) {
+               fprintf(stderr, "yppush: %s%s: Cannot open database\n",
+                       map_path, YPDB_SUFFIX);
+       } else {
+               o.dptr = (char *) &order_key;
+               o.dsize = YP_LAST_LEN;
+               o=ypdb_fetch(yp_databas,o);
+               if (o.dptr == NULL) {
+                       fprintf(stderr,
+                               "yppush: %s: Cannot determine order number\n",
+                               Map);
+               } else {
+                       OrderNum=0;
+                       for(i=0; i<o.dsize-1; i++) {
+                               if (!isdigit(o.dptr[i])) {
+                                       OrderNum=0xffffffff;
+                               }
+                       }
+                       if (OrderNum != 0) {
+                               fprintf(stderr,
+                                       "yppush: %s: Invalid order number '%s'\n",
+                                       Map,
+                                       o.dptr);
+                       } else {
+                               OrderNum = atoi(o.dptr);
+                       }
+               }
+        }
+       
+
+       yp_bind(Domain);
+
+       r = yp_master(Domain, ypmap, &master);
+        if (r != 0) {
+               fprintf(stderr, "yppush: could not get ypservers map\n");
+               exit(1);
+       }
+
+       if (hostname != NULL) {
+         push(strlen(hostname), hostname);
+       } else {
+         
+         if (Verbose) {
+               printf("Contacting master for ypservers (%s).\n", master);
+         }
+
+         client = yp_bind_host(master, YPPROG, YPVERS, 0, 1);
+
+         ypcb.foreach = pushit;
+         ypcb.data = NULL;
+
+         r = yp_all_host(client,Domain, ypmap, &ypcb);
+       }
+        
+        exit(0);
+}
+
diff --git a/yppush.tproj/yppush.h b/yppush.tproj/yppush.h
new file mode 100644 (file)
index 0000000..9aa8dc5
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppush.h,v 1.3 1997/07/25 20:12:32 mickey Exp $ */
+
+/*
+ * Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPPUSH_H_RPCGEN
+#define _YPPUSH_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+enum yppush_status {
+       YPPUSH_SUCC = 1,
+       YPPUSH_AGE = 2,
+       YPPUSH_NOMAP = -1,
+       YPPUSH_NODOM = -2,
+       YPPUSH_RSRC = -3,
+       YPPUSH_RPC = -4,
+       YPPUSH_MADDR = -5,
+       YPPUSH_YPERR = -6,
+       YPPUSH_BADARGS = -7,
+       YPPUSH_DBM = -8,
+       YPPUSH_FILE = -9,
+       YPPUSH_SKEW = -10,
+       YPPUSH_CLEAR = -11,
+       YPPUSH_FORCE = -12,
+       YPPUSH_XFRERR = -13,
+       YPPUSH_REFUSED = -14,
+};
+typedef enum yppush_status yppush_status;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_yppush_status(XDR *, yppush_status*);
+#elif defined(__STDC__)
+extern  bool_t xdr_yppush_status(XDR *, yppush_status*);
+#else /* Old Style C */ 
+bool_t xdr_yppush_status();
+#endif /* Old Style C */ 
+
+
+struct yppushresp_xfr {
+       u_int transid;
+       yppush_status status;
+};
+typedef struct yppushresp_xfr yppushresp_xfr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*);
+#elif defined(__STDC__)
+extern  bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*);
+#else /* Old Style C */ 
+bool_t xdr_yppushresp_xfr();
+#endif /* Old Style C */ 
+
+
+#define YPPUSH_XFRRESPPROG ((u_long)0x40000000)
+#define YPPUSH_XFRRESPVERS ((u_long)1)
+
+#ifdef __cplusplus
+#define YPPUSHPROC_NULL ((u_long)0)
+extern "C" void * yppushproc_null_1(void *, CLIENT *);
+extern "C" void * yppushproc_null_1_svc(void *, struct svc_req *);
+#define YPPUSHPROC_XFRRESP ((u_long)1)
+extern "C" void * yppushproc_xfrresp_1(yppushresp_xfr *, CLIENT *);
+extern "C" void * yppushproc_xfrresp_1_svc(yppushresp_xfr *, struct svc_req *);
+
+#elif defined(__STDC__)
+#define YPPUSHPROC_NULL ((u_long)0)
+extern  void * yppushproc_null_1(void *, CLIENT *);
+extern  void * yppushproc_null_1_svc(void *, struct svc_req *);
+#define YPPUSHPROC_XFRRESP ((u_long)1)
+extern  void * yppushproc_xfrresp_1(yppushresp_xfr *, CLIENT *);
+extern  void * yppushproc_xfrresp_1_svc(yppushresp_xfr *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define YPPUSHPROC_NULL ((u_long)0)
+extern  void * yppushproc_null_1();
+extern  void * yppushproc_null_1_svc();
+#define YPPUSHPROC_XFRRESP ((u_long)1)
+extern  void * yppushproc_xfrresp_1();
+extern  void * yppushproc_xfrresp_1_svc();
+#endif /* Old Style C */ 
+
+#endif /* !_YPPUSH_H_RPCGEN */
diff --git a/yppush.tproj/yppush_err.c b/yppush.tproj/yppush_err.c
new file mode 100644 (file)
index 0000000..31f74e8
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppush_err.c,v 1.2 1996/05/30 09:53:20 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$OpenBSD: yppush_err.c,v 1.2 1996/05/30 09:53:20 deraadt Exp $";
+#endif /* not lint */
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp.h>
+
+char *
+yppush_err_string(enum yppush_status y) {
+       switch(y) {
+       case YPPUSH_SUCC:
+                       return "Success";
+       case YPPUSH_AGE:
+                       return "Master's version not newer";
+       case YPPUSH_NOMAP:
+                       return "Can't find server for map";
+       case YPPUSH_NODOM:
+                       return "Domain not supported";
+       case YPPUSH_RSRC:
+                       return "Local resource alloc failure";
+       case YPPUSH_RPC:
+                       return "RPC failure talking to server";
+       case YPPUSH_MADDR:
+                       return "Can't get master address";
+       case YPPUSH_YPERR:
+                       return "YP server/map db error";
+       case YPPUSH_BADARGS:
+                       return "Request arguments bad";
+       case YPPUSH_DBM:
+                       return "Local dbm operation failed";
+       case YPPUSH_FILE:
+                       return "Local file I/O operation failed";
+       case YPPUSH_SKEW:
+                       return "Map version skew during transfer";
+       case YPPUSH_CLEAR:
+                       return "Can't send \"Clear\" req to local ypserv";
+       case YPPUSH_FORCE:
+                       return "No local order number in map  use -f flag.";
+       case YPPUSH_XFRERR:
+                       return "ypxfr error";
+       case YPPUSH_REFUSED:
+                       return "Transfer request refused by ypserv";
+        }
+};
diff --git a/yppush.tproj/yppush_proc.c b/yppush.tproj/yppush_proc.c
new file mode 100644 (file)
index 0000000..601a7cb
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppush_proc.c,v 1.3 1997/08/21 12:52:08 maja Exp $ */
+
+/*
+ * Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$OpenBSD: yppush_proc.c,v 1.3 1997/08/21 12:52:08 maja Exp $";
+#endif /* not lint */
+
+#include <stdio.h>
+#include "yppush.h"
+
+extern int Verbose;
+
+void * 
+yppushproc_null_1_svc(argp, rqstp)
+       void *argp;
+       struct svc_req *rqstp;
+{
+
+       static char* result;
+
+       /*
+        * insert server code here
+        */
+       return((void*) &result);
+}
+
+void * 
+yppushproc_xfrresp_1_svc(argp, rqstp)
+       yppushresp_xfr *argp;
+       struct svc_req *rqstp;
+{
+
+       static char* result;
+
+       /*
+        * insert server code here
+        */
+       if ((argp->status<YPPUSH_SUCC) || Verbose)
+               fprintf(stderr,"yppush: %s\n",
+                               yppush_err_string(argp->status));
+
+       return((void*) &result);
+}
diff --git a/yppush.tproj/yppush_svc.c b/yppush.tproj/yppush_svc.c
new file mode 100644 (file)
index 0000000..f3c19dc
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppush_svc.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$OpenBSD: yppush_svc.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $";
+#endif /* not lint */
+
+#include "yppush.h"
+#include <stdio.h>
+#include <stdlib.h>/* getenv, exit */
+#include <netdb.h>
+#include <signal.h>
+#include <sys/ttycom.h>/* TIOCNOTTY */
+#include <memory.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef SYSLOG
+#include <syslog.h>
+#else
+#define LOG_ERR 1
+#define openlog(a, b, c)
+#endif
+
+#ifdef __STDC__
+#define SIG_PF void(*)(int)
+#endif
+
+#ifdef DEBUG
+#define RPC_SVC_FG
+#endif
+
+#define _RPCSVC_CLOSEDOWN 120
+int _rpcpmstart;               /* Started by a port monitor ? */
+int _rpcfdtype;                        /* Whether Stream or Datagram ? */
+int _rpcsvcdirty;              /* Still serving ? */
+
+static
+void _msgout(msg)
+       char *msg;
+{
+#ifdef RPC_SVC_FG
+       if (_rpcpmstart)
+               syslog(LOG_ERR, msg);
+       else
+               (void) fprintf(stderr, "%s\n", msg);
+#else
+       syslog(LOG_ERR, msg);
+#endif
+}
+
+void
+yppush_xfrrespprog_1(rqstp, transp)
+       struct svc_req *rqstp;
+       register SVCXPRT *transp;
+{
+       union {
+               int fill;
+       } argument;
+       char *result;
+       bool_t (*xdr_argument)(), (*xdr_result)();
+       char *(*local)();
+
+       _rpcsvcdirty = 1;
+       switch (rqstp->rq_proc) {
+       case YPPUSHPROC_NULL:
+               xdr_argument = xdr_void;
+               xdr_result = xdr_void;
+               local = (char *(*)()) yppushproc_null_1_svc;
+               break;
+
+       case YPPUSHPROC_XFRRESP:
+               xdr_argument = xdr_yppushresp_xfr;
+               xdr_result = xdr_void;
+               local = (char *(*)()) yppushproc_xfrresp_1_svc;
+               break;
+
+       default:
+               svcerr_noproc(transp);
+               _rpcsvcdirty = 0;
+               exit(1);
+               return;
+       }
+       (void) memset((char *)&argument, 0, sizeof (argument));
+       if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
+               svcerr_decode(transp);
+               _rpcsvcdirty = 0;
+               exit(1);
+               return;
+       }
+       result = (*local)(&argument, rqstp);
+       if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+               svcerr_systemerr(transp);
+       }
+       if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
+               _msgout("unable to free arguments");
+               exit(1);
+       }
+       _rpcsvcdirty = 0;
+       if (rqstp->rq_proc!=YPPUSHPROC_NULL)
+               exit(0);
+       return;
+}
diff --git a/yppush.tproj/yppush_xdr.c b/yppush.tproj/yppush_xdr.c
new file mode 100644 (file)
index 0000000..d8ad787
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yppush_xdr.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: yppush_xdr.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $";
+#endif
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp.h>
+
+__private_extern__
+bool_t
+xdr_domainname(xdrs, objp)
+       XDR *xdrs;
+       domainname *objp;
+{
+       if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_mapname(xdrs, objp)
+       XDR *xdrs;
+       mapname *objp;
+{
+       if (!xdr_string(xdrs, objp, YPMAXMAP)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_peername(xdrs, objp)
+       XDR *xdrs;
+       peername *objp;
+{
+       if (!xdr_string(xdrs, objp, YPMAXPEER)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypmap_parms(xdrs, objp)
+       XDR *xdrs;
+       ypmap_parms *objp;
+{
+       if (!xdr_domainname(xdrs, &objp->domain)) {
+               return (FALSE);
+       }
+       if (!xdr_mapname(xdrs, &objp->map)) {
+               return (FALSE);
+       }
+       if (!xdr_u_int(xdrs, &objp->ordernum)) {
+               return (FALSE);
+       }
+       if (!xdr_peername(xdrs, &objp->peer)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypreq_xfr(xdrs, objp)
+       XDR *xdrs;
+       ypreq_xfr *objp;
+{
+       if (!xdr_ypmap_parms(xdrs, &objp->map_parms)) {
+               return (FALSE);
+       }
+       if (!xdr_u_int(xdrs, &objp->transid)) {
+               return (FALSE);
+       }
+       if (!xdr_u_int(xdrs, &objp->prog)) {
+               return (FALSE);
+       }
+       if (!xdr_u_int(xdrs, &objp->port)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+bool_t
+xdr_yppush_status(xdrs, objp)
+       XDR *xdrs;
+       yppush_status *objp;
+{
+        register long *buf;
+
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_yppushresp_xfr(xdrs, objp)
+       XDR *xdrs;
+       yppushresp_xfr *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_u_int(xdrs, &objp->transid)) {
+                return (FALSE);
+        }
+        if (!xdr_yppush_status(xdrs, &objp->status)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+
+
diff --git a/ypserv.tproj/Makefile b/ypserv.tproj/Makefile
new file mode 100644 (file)
index 0000000..626fbef
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ypserv
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = acl.h yp.h ypv1.h ypdb.h yplog.h ypdef.h
+
+CFILES = acl.c ypdb.c yplog.c ypserv.c ypserv_db.c ypserv_proc.c\
+         ypserv_xdr.c ypserv_xdr_v1.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble securenet\
+            securenet.5 ypserv.acl ypserv.acl.5
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ypserv.tproj/Makefile.postamble b/ypserv.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/ypserv.tproj/Makefile.preamble b/ypserv.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/ypserv.tproj/PB.project b/ypserv.tproj/PB.project
new file mode 100644 (file)
index 0000000..c7cbbbb
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (acl.h, yp.h, ypv1.h, ypdb.h, yplog.h, ypdef.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (
+            acl.c, 
+            ypdb.c, 
+            yplog.c, 
+            ypserv.c, 
+            ypserv_db.c, 
+            ypserv_proc.c, 
+            ypserv_xdr.c, 
+            ypserv_xdr_v1.c
+        ); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            securenet, 
+            securenet.5, 
+            ypserv.acl, 
+            ypserv.acl.5
+        ); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ypserv; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ypserv.tproj/acl.c b/ypserv.tproj/acl.c
new file mode 100644 (file)
index 0000000..14e767f
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: acl.c,v 1.5 1997/08/05 09:26:55 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: acl.c,v 1.5 1997/08/05 09:26:55 maja Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <netdb.h>
+#include "acl.h"
+
+#define TRUE 1
+#define FALSE 0
+
+static struct aclent *acl_root = NULL;
+
+static int acl_read_line(fp, buf, size)
+FILE *fp;
+char *buf;
+int size;
+{
+  int   len = 0;
+  char *c,*p,l;
+
+  /* Read a line, and remove any comment, trim space */
+
+  do {
+    while (fgets(buf, size, fp)) {
+      c = buf;
+      while(*c != '\0') {
+       if ((*c == '#') || (*c == '\n')) {
+         *c = '\0';
+       } else {
+         c++;
+       }
+      }
+
+      c = p = buf; l = ' ';
+      while(*c != '\0') {
+       if ((isspace(l) != 0) && (isspace(*c) != 0)) {
+         c++;
+       } else {
+         l = *c++; *p = l; p++;
+       }
+      }
+      *p = '\0';
+      
+      if (p != buf) {
+       --p;
+       if (isspace(*p) != 0) {
+         *p = '\0';
+       }
+      }
+
+      len = strlen(buf);
+      return len + 1;
+    }
+  } while (size > 0 && !feof(fp));
+  
+  return len;
+}
+
+int
+acl_check_host(addr)
+struct in_addr *addr;
+{
+  struct aclent *p;
+  
+  p = acl_root;
+  while (p != NULL) {
+    if ((addr->s_addr & p->s_mask) == p->s_addr) {
+      return(p->allow);
+    }
+    p = p->next;
+  }
+  return(TRUE);
+}
+
+void
+acl_add_net(allow,addr,mask)
+int    allow;
+struct in_addr *addr,*mask;
+{
+  
+  struct aclent *acl,*p;
+  
+  acl = (struct aclent *) malloc((unsigned) sizeof(struct aclent));
+  
+  acl->next   = NULL;
+  acl->allow  = allow;
+  acl->s_addr = addr->s_addr;
+  acl->s_mask = mask->s_addr;
+  
+  if (acl_root == NULL) {
+    acl_root = acl;
+  } else {
+    p = acl_root;
+    while (p->next != NULL)
+      p = p->next;
+    p->next = acl;
+  }
+  
+} 
+
+void
+acl_add_host(allow,addr)
+int    allow;
+struct in_addr *addr;
+{
+       struct in_addr mask;
+
+       mask.s_addr = htonl(0xffffffff);
+       
+       acl_add_net(allow,addr,&mask);
+}
+
+int
+acl_init(file)
+char *file;
+{
+  char  data_line[1024];
+  int   line_no = 0;
+  int   len,i;
+  int   allow = TRUE;
+  int   error_cnt = 0;
+  char *p,*k;
+  int   state;
+  struct in_addr addr,mask,*host_addr;
+  struct hostent *host;
+  struct netent  *net;
+  FILE  *data_file = NULL;
+  
+  if (file != NULL) {
+    data_file = fopen(file,"r");
+  };
+
+  while ((data_file != NULL) &&
+        (acl_read_line(data_file,data_line,sizeof(data_line)))) {
+    
+    line_no++;
+    
+    len = strlen(data_line);
+    if (len == 0) {
+      continue;
+    }
+
+    p = (char *) &data_line;
+
+    /* State 1: Initial State */
+
+    state = ACLS_INIT;
+    addr.s_addr = mask.s_addr = 0;
+
+    k = p; i = 0;                              /* save start of verb */
+    while ((*p != '\0') &&
+          (!isspace(*p = tolower(*p)))) {
+      p++; i++;
+    };
+
+    if (*p != '\0') {
+      *p++ = '\0';
+    }
+
+    if (strcmp(k,"allow") == 0) {
+      allow = TRUE;
+      state = ACLS_ALLOW;
+    }
+
+    if (strcmp(k,"deny") == 0) {
+      allow = FALSE;
+      state = ACLS_DENY;
+    }
+
+    if (state == ACLS_INIT) {
+      state = ACLE_UVERB;
+    }
+
+    /* State 2: allow row */
+    /* State 3: deny row */
+
+    if ((*p != '\0') &&
+       ((state == ACLS_ALLOW) || (state == ACLS_DENY))) {
+      
+      k = p; i = 0;                            /* save start of verb */
+      while ((*p != '\0') &&
+            (!isspace(*p = tolower(*p)))) {
+       p++; i++;
+      };
+      
+      if (*p != '\0') {
+       *p++ = '\0';
+      }
+
+      if (strcmp(k,"all") == 0) {
+       state = state + ACLD_ALL;
+      }
+
+      if (strcmp(k,"host") == 0) {
+       state = state + ACLD_HOST;
+      }
+
+      if (strcmp(k,"net") == 0) {
+       state = state + ACLD_NET;
+      }
+
+      if ((state == ACLS_ALLOW) || (state == ACLS_DENY)) {
+       state = ACLE_U2VERB;
+      }
+      
+    }
+
+    if ((state == ACLS_ALLOW) || (state == ACLS_DENY)) {
+      state = ACLE_UEOL;
+    }
+
+    /* State 4 & 5: all state, remove any comment */
+
+    if ((*p == '\0') &&
+       ((state == ACLS_ALLOW_ALL) || (state == ACLS_DENY_ALL))) {
+      acl_add_net(allow,&addr,&mask);
+      state = ACLE_OK;
+    }
+      
+    /* State 6 & 7: host line */
+    /* State 8 & 9: net line */
+
+    if ((*p != '\0') &&
+       (state >= ACLS_ALLOW_HOST) && (state <= ACLS_DENY_NET)) {
+      
+      k = p; i = 0;                            /* save start of verb */
+      while ((*p != '\0') &&
+            (!isspace(*p = tolower(*p)))) {
+       p++; i++;
+      };
+      
+      if (*p != '\0') {
+       *p++ = '\0';
+      }
+      
+      if ((state == ACLS_ALLOW_HOST) || (state == ACLS_DENY_HOST)) {
+       if ((*k >= '0') && (*k <= '9')) {
+         (void)inet_aton(k,&addr);
+         acl_add_host(allow,&addr);
+         state = state + ACLD_HOST_DONE;
+        } else {
+         host = gethostbyname(k);
+         if (host == NULL) {
+           state = ACLE_NOHOST;
+         } else {
+           if (host->h_addrtype == AF_INET) {
+             while ((host_addr = (struct in_addr *) *host->h_addr_list++)
+                    != NULL)
+               acl_add_host(allow,host_addr);
+           }
+           state = state + ACLD_HOST_DONE;
+         }
+       }
+      }
+
+      if ((state == ACLS_ALLOW_NET) || (state == ACLS_DENY_NET)) {
+       if ((*k >= '0') && (*k <= '9')) {
+         (void)inet_aton(k,&addr);
+         state = state + ACLD_NET_DONE;
+        } else {
+         net = getnetbyname(k);
+         if (net == NULL) {
+           state = ACLE_NONET;
+         } else {
+           addr.s_addr = ntohl(net->n_net);
+           state = state + ACLD_NET_DONE;
+         }
+       }
+      }
+
+    }
+
+    if ((state >= ACLS_ALLOW_HOST) && (state <= ACLS_DENY_NET)) {
+      state = ACLE_UEOL;
+    }
+
+    /* State 10 & 11: allow/deny host line */
+
+    if ((*p == '\0') &&
+       ((state == ACLS_ALLOW_HOST_DONE) || (state == ACLS_DENY_HOST_DONE))) {
+      state = ACLE_OK;
+    }
+      
+    /* State 12 & 13: allow/deny net line */
+
+    if ((*p == '\0') &&
+       ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE))) {
+      mask.s_addr = htonl(0xffffff00);
+      if (ntohl(addr.s_addr) < 0xc0000000) {
+       mask.s_addr = htonl(0xffff0000);
+      }
+      if (ntohl(addr.s_addr) < 0x80000000) {
+       mask.s_addr = htonl(0xff000000);
+      }
+      acl_add_net(allow,&addr,&mask);
+      state = ACLE_OK;
+    }
+
+    if ((*p != '\0') &&
+       ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE))) {
+      
+      k = p; i = 0;                            /* save start of verb */
+      while ((*p != '\0') &&
+            (!isspace(*p = tolower(*p)))) {
+       p++; i++;
+      };
+      
+      if (*p != '\0') {
+       *p++ = '\0';
+      }
+
+      if (strcmp(k,"netmask") == 0) {
+       state = state + ACLD_NET_MASK;
+      }
+
+      if ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE)) {
+       state = ACLE_NONETMASK;
+      }
+      
+    }
+
+    /* State 14 & 15: allow/deny net netmask line */
+
+    if ((*p != '\0') &&
+       ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK))) {
+      
+      k = p; i = 0;                            /* save start of verb */
+      while ((*p != '\0') &&
+            (!isspace(*p = tolower(*p)))) {
+       p++; i++;
+      };
+      
+      if (*p != '\0') {
+       *p++ = '\0';
+      }
+
+      if ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK)) {
+       if ((*k >= '0') && (*k <= '9')) {
+         (void)inet_aton(k,&mask);
+         state = state + ACLD_NET_EOL;
+        } else {
+         net = getnetbyname(k);
+         if (net == NULL) {
+           state = ACLE_NONET;
+         } else {
+           mask.s_addr = ntohl(net->n_net);
+           state = state + ACLD_NET_EOL;
+         }
+       }
+      }
+
+    }
+
+    if ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK)) {
+      state = ACLE_UEOL;
+    }
+
+    /* State 16 & 17: allow/deny host line */
+
+    if ((*p == '\0') &&
+       ((state == ACLS_ALLOW_NET_EOL) || (state == ACLS_DENY_NET_EOL))) {
+      acl_add_net(allow,&addr,&mask);
+      state = ACLE_OK;
+    }
+      
+    switch (state) {
+    case  ACLE_NONETMASK:
+      fprintf(stderr,"acl: excpected \"netmask\" missing at line %d\n",line_no);
+      break;
+    case  ACLE_NONET:
+      error_cnt++;
+      fprintf(stderr,"acl: unknown network at line %d\n",line_no);
+      break;
+    case  ACLE_NOHOST:
+      error_cnt++;
+      fprintf(stderr,"acl: unknown host at line %d\n",line_no);
+      break;
+    case  ACLE_UVERB:
+      error_cnt++;
+      fprintf(stderr,"acl: unknown verb at line %d\n",line_no);
+      break;
+    case ACLE_U2VERB:
+      error_cnt++;
+      fprintf(stderr,"acl: unknown secondary verb at line %d\n",line_no);
+      break;
+    case ACLE_UEOL:
+      error_cnt++;
+      fprintf(stderr,"acl: unexpected end of line at line %d\n",line_no);
+      break;
+    case ACLE_OK:
+      break;
+    default:
+      error_cnt++;
+      fprintf(stderr,"acl: unexpected state %d %s\n",state,k);
+    }
+
+  }
+
+  if (data_file != NULL) {
+    (void)fflush(stderr);
+    (void)fclose(data_file);
+  }
+
+  /* Always add a last allow all if file don't exists or */
+  /* the file doesn't cover all cases.                   */
+  
+  addr.s_addr = mask.s_addr = 0;
+  allow = TRUE;
+  acl_add_net(allow,&addr,&mask);
+
+  return(error_cnt);
+
+}
+
+int
+acl_securenet(file)
+char *file;
+{
+  char  data_line[1024];
+  int   line_no = 0;
+  int   len,i;
+  int   allow = TRUE;
+  int   error_cnt = 0;
+  char *p,*k;
+  int   state;
+  struct in_addr addr,mask;
+  struct netent  *net;
+  FILE  *data_file = NULL;
+  
+  if (file != NULL) {
+    data_file = fopen(file,"r");
+  };
+
+  /* Always add a localhost allow first, to be compatable with sun */
+  
+  addr.s_addr = htonl(0x7f000001);
+  mask.s_addr = htonl(0xffffffff);
+  allow = TRUE;
+  acl_add_net(allow,&addr,&mask);
+
+  while ((data_file != NULL) &&
+        (acl_read_line(data_file,data_line,sizeof(data_line)))) {
+    
+    line_no++;
+    
+    len = strlen(data_line);
+    if (len == 0) {
+      continue;
+    }
+
+    p = (char *) &data_line;
+
+    /* State 1: Initial State */
+
+    state = ACLS_INIT;
+    addr.s_addr = mask.s_addr = 0;
+
+    k = p; i = 0;                              /* save start of verb */
+    while ((*p != '\0') &&
+          (!isspace(*p = tolower(*p)))) {
+      p++; i++;
+    };
+    
+    if (*p != '\0') {
+      *p++ = '\0';
+      state = ACLS_ALLOW_NET_MASK;
+    }
+    
+    if (state == ACLS_INIT) {
+      state = ACLE_UEOL;
+    }
+
+    if (state == ACLS_ALLOW_NET_MASK) {
+      
+      if ((*k >= '0') && (*k <= '9')) {
+       (void)inet_aton(k,&mask);
+       state = ACLS_ALLOW_NET;
+      } else {
+       net = getnetbyname(k);
+       if (net == NULL) {
+         state = ACLE_NONET;
+       } else {
+         mask.s_addr = ntohl(net->n_net);
+         state = ACLS_ALLOW_NET;
+       }
+      }
+      
+      k = p; i = 0;                            /* save start of verb */
+      while ((*p != '\0') &&
+            (!isspace(*p = tolower(*p)))) {
+       p++; i++;
+      };
+      
+      if (*p != '\0') {
+       *p++ = '\0';
+      }
+    }
+    
+    if ((state == ACLS_ALLOW_NET_MASK)) {
+      state = ACLE_UEOL;
+    }
+
+    if (state == ACLS_ALLOW_NET) {
+      
+      if ((*k >= '0') && (*k <= '9')) {
+       (void)inet_aton(k,&addr);
+       state = ACLS_ALLOW_NET_EOL;
+      } else {
+       net = getnetbyname(k);
+       if (net == NULL) {
+         state = ACLE_NONET;
+       } else {
+         addr.s_addr = ntohl(net->n_net);
+         state = ACLS_ALLOW_NET_EOL;
+       }
+      }
+    }
+      
+    if ((state == ACLS_ALLOW_NET)) {
+      state = ACLE_UEOL;
+    }
+
+    if ((*p == '\0') &&        (state == ACLS_ALLOW_NET_EOL)) {
+      acl_add_net(allow,&addr,&mask);
+      state = ACLE_OK;
+    }
+      
+    switch (state) {
+    case  ACLE_NONET:
+      error_cnt++;
+      fprintf(stderr,"securenet: unknown network at line %d\n",line_no);
+      break;
+    case ACLE_UEOL:
+      error_cnt++;
+      fprintf(stderr,"securenet: unexpected end of line at line %d\n",line_no);
+      break;
+    case ACLE_OK:
+      break;
+    default:
+      error_cnt++;
+      fprintf(stderr,"securenet: unexpected state %d %s\n",state,k);
+    }
+
+  }
+
+  if (data_file != NULL) {
+    (void)fflush(stderr);
+    (void)fclose(data_file);
+    
+    /* Always add a last deny all if file exists */
+    
+    addr.s_addr = mask.s_addr = 0;
+    allow = FALSE;
+    acl_add_net(allow,&addr,&mask);
+
+  }
+
+  /* Always add a last allow all if file don't exists */
+  
+  addr.s_addr = mask.s_addr = 0;
+  allow = TRUE;
+  acl_add_net(allow,&addr,&mask);
+
+  return(error_cnt);
+
+}
+
+void
+acl_reset()
+{
+       struct aclent *p;
+
+       while (acl_root != NULL) {
+               p = acl_root->next;
+               free(acl_root);
+               acl_root = p;
+       }
+}
diff --git a/ypserv.tproj/acl.h b/ypserv.tproj/acl.h
new file mode 100644 (file)
index 0000000..cb10663
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: acl.h,v 1.4 1996/06/30 19:46:05 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ACL_H_
+#define _ACL_H_
+
+#define ACLD_ALL               2
+#define ACLD_HOST              4
+#define ACLD_NET               6
+#define ACLD_HOST_DONE         4
+#define ACLD_NET_DONE          4
+#define ACLD_NET_MASK          2
+#define ACLD_NET_EOL           2
+
+#define ACLS_INIT              1
+#define ACLS_ALLOW             2
+#define ACLS_DENY              3
+#define ACLS_ALLOW_ALL         ACLS_ALLOW+ACLD_ALL               /*  4 */
+#define ACLS_DENY_ALL          ACLS_DENY+ACLD_ALL                /*  5 */
+#define ACLS_ALLOW_HOST                ACLS_ALLOW+ACLD_HOST              /*  6 */
+#define ACLS_DENY_HOST         ACLS_DENY+ACLD_HOST               /*  7 */
+#define ACLS_ALLOW_NET         ACLS_ALLOW+ACLD_NET               /*  8 */
+#define ACLS_DENY_NET          ACLS_DENY+ACLD_NET                /*  9 */
+#define ACLS_ALLOW_HOST_DONE   ACLS_ALLOW_HOST+ACLD_HOST_DONE    /* 10 */
+#define ACLS_DENY_HOST_DONE    ACLS_DENY_HOST+ACLD_HOST_DONE     /* 11 */
+#define ACLS_ALLOW_NET_DONE    ACLS_ALLOW_NET+ACLD_NET_DONE      /* 12 */
+#define ACLS_DENY_NET_DONE     ACLS_DENY_NET+ACLD_NET_DONE       /* 13 */
+#define ACLS_ALLOW_NET_MASK    ACLS_ALLOW_NET_DONE+ACLD_NET_MASK /* 14 */
+#define ACLS_DENY_NET_MASK     ACLS_DENY_NET_DONE+ACLD_NET_MASK  /* 15 */
+#define ACLS_ALLOW_NET_EOL     ACLS_ALLOW_NET_MASK+ACLD_NET_EOL  /* 16 */
+#define ACLS_DENY_NET_EOL      ACLS_DENY_NET_MASK+ACLD_NET_EOL   /* 17 */
+
+#define ACLE_NONETMASK         18
+#define ACLE_NONET             19
+#define ACLE_NOHOST            20
+#define ACLE_UVERB             21
+#define ACLE_U2VERB            22
+#define ACLE_UEOL              23
+#define ACLE_OK                        24
+
+struct aclent {
+struct aclent  *next;
+       int     allow;
+       u_long  s_addr;
+       u_long  s_mask;
+};
+
+__BEGIN_DECLS
+int            acl_check_host __P((struct in_addr *));
+int            acl_init __P((char *));
+int            acl_securenet __P((char *));
+void           acl_reset __P((void));
+__END_DECLS
+
+#endif /* !_ACL_H_ */
+
+
diff --git a/ypserv.tproj/securenet b/ypserv.tproj/securenet
new file mode 100644 (file)
index 0000000..a136cfb
--- /dev/null
@@ -0,0 +1,4 @@
+#
+# Only my local net is secure. 
+#
+255.255.255.0 139.58.253.0
diff --git a/ypserv.tproj/securenet.5 b/ypserv.tproj/securenet.5
new file mode 100644 (file)
index 0000000..bb14ae7
--- /dev/null
@@ -0,0 +1,74 @@
+.\"    $OpenBSD: securenet.5,v 1.4 1996/06/26 21:26:37 maja Exp $
+.\" Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd June 27, 1994
+.Dt SECURENET 5
+.Os
+.Sh NAME
+.Nm securenet
+.Nd 
+.Xr ypserv 8
+configuration file for secure networks
+.Sh DESCRIPTION
+The 
+.Nm securenet
+file controls which hosts can connect to the
+.Nm YP
+server.
+.Pp
+The format is rather simple. Each row consists of two items. The first item
+is the network mask. The second item is the network.
+.Sh EXAMPLES
+.Pp
+A configuration file might appear as follows:
+.Bd -literal
+#
+# Only my local net is secure. 
+#
+255.255.255.0 139.58.253.0
+.Ed
+.Sh FILES
+.Bl -tag -width /var/yp/securenet -compact
+.It Pa /var/yp/securenet
+A
+.Xr ypserv 8
+configuration file.
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr ypserv 8 ,
+.Xr ypserv.acl 5
+.Sh HISTORY
+The
+.Nm securenet
+was added to
+.Nm NIS
+by Sun Microsystems, Inc. as a bugfix for weak security.
+
diff --git a/ypserv.tproj/yp.h b/ypserv.tproj/yp.h
new file mode 100644 (file)
index 0000000..cfe590b
--- /dev/null
@@ -0,0 +1,612 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $OpenBSD: yp.h,v 1.5 1997/07/25 20:12:31 mickey Exp $ */
+
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _YP_H_RPCGEN
+#define _YP_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+#define YPMAXRECORD 1024
+#define YPMAXDOMAIN 64
+#define YPMAXMAP 64
+#define YPMAXPEER 64
+
+enum ypstat {
+       YP_TRUE = 1,
+       YP_NOMORE = 2,
+       YP_FALSE = 0,
+       YP_NOMAP = -1,
+       YP_NODOM = -2,
+       YP_NOKEY = -3,
+       YP_BADOP = -4,
+       YP_BADDB = -5,
+       YP_YPERR = -6,
+       YP_BADARGS = -7,
+       YP_VERS = -8,
+};
+typedef enum ypstat ypstat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypstat(XDR *, ypstat*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypstat(XDR *, ypstat*);
+#else /* Old Style C */ 
+bool_t xdr_ypstat();
+#endif /* Old Style C */ 
+
+
+enum ypxfrstat {
+       YPXFR_SUCC = 1,
+       YPXFR_AGE = 2,
+       YPXFR_NOMAP = -1,
+       YPXFR_NODOM = -2,
+       YPXFR_RSRC = -3,
+       YPXFR_RPC = -4,
+       YPXFR_MADDR = -5,
+       YPXFR_YPERR = -6,
+       YPXFR_BADARGS = -7,
+       YPXFR_DBM = -8,
+       YPXFR_FILE = -9,
+       YPXFR_SKEW = -10,
+       YPXFR_CLEAR = -11,
+       YPXFR_FORCE = -12,
+       YPXFR_XFRERR = -13,
+       YPXFR_REFUSED = -14,
+};
+typedef enum ypxfrstat ypxfrstat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypxfrstat(XDR *, ypxfrstat*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypxfrstat(XDR *, ypxfrstat*);
+#else /* Old Style C */ 
+bool_t xdr_ypxfrstat();
+#endif /* Old Style C */ 
+
+
+typedef char *domainname;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_domainname(XDR *, domainname*);
+#elif defined(__STDC__)
+extern  bool_t xdr_domainname(XDR *, domainname*);
+#else /* Old Style C */ 
+bool_t xdr_domainname();
+#endif /* Old Style C */ 
+
+
+typedef char *mapname;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_mapname(XDR *, mapname*);
+#elif defined(__STDC__)
+extern  bool_t xdr_mapname(XDR *, mapname*);
+#else /* Old Style C */ 
+bool_t xdr_mapname();
+#endif /* Old Style C */ 
+
+
+typedef char *peername;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_peername(XDR *, peername*);
+#elif defined(__STDC__)
+extern  bool_t xdr_peername(XDR *, peername*);
+#else /* Old Style C */ 
+bool_t xdr_peername();
+#endif /* Old Style C */ 
+
+
+typedef struct {
+       u_int keydat_len;
+       char *keydat_val;
+} keydat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_keydat(XDR *, keydat*);
+#elif defined(__STDC__)
+extern  bool_t xdr_keydat(XDR *, keydat*);
+#else /* Old Style C */ 
+bool_t xdr_keydat();
+#endif /* Old Style C */ 
+
+
+typedef struct {
+       u_int valdat_len;
+       char *valdat_val;
+} valdat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_valdat(XDR *, valdat*);
+#elif defined(__STDC__)
+extern  bool_t xdr_valdat(XDR *, valdat*);
+#else /* Old Style C */ 
+bool_t xdr_valdat();
+#endif /* Old Style C */ 
+
+
+struct ypmap_parms {
+       domainname domain;
+       mapname map;
+       u_int32_t ordernum;
+       peername peer;
+};
+typedef struct ypmap_parms ypmap_parms;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypmap_parms(XDR *, ypmap_parms*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypmap_parms(XDR *, ypmap_parms*);
+#else /* Old Style C */ 
+bool_t xdr_ypmap_parms();
+#endif /* Old Style C */ 
+
+
+struct ypreq_key {
+       domainname domain;
+       mapname map;
+       keydat key;
+};
+typedef struct ypreq_key ypreq_key;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypreq_key(XDR *, ypreq_key*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypreq_key(XDR *, ypreq_key*);
+#else /* Old Style C */ 
+bool_t xdr_ypreq_key();
+#endif /* Old Style C */ 
+
+
+struct ypreq_nokey {
+       domainname domain;
+       mapname map;
+};
+typedef struct ypreq_nokey ypreq_nokey;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypreq_nokey(XDR *, ypreq_nokey*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypreq_nokey(XDR *, ypreq_nokey*);
+#else /* Old Style C */ 
+bool_t xdr_ypreq_nokey();
+#endif /* Old Style C */ 
+
+
+struct ypreq_xfr {
+       ypmap_parms map_parms;
+       u_int transid;
+       u_int prog;
+       u_int port;
+};
+typedef struct ypreq_xfr ypreq_xfr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypreq_xfr(XDR *, ypreq_xfr*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypreq_xfr(XDR *, ypreq_xfr*);
+#else /* Old Style C */ 
+bool_t xdr_ypreq_xfr();
+#endif /* Old Style C */ 
+
+
+struct ypresp_val {
+       ypstat stat;
+       valdat val;
+};
+typedef struct ypresp_val ypresp_val;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresp_val(XDR *, ypresp_val*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresp_val(XDR *, ypresp_val*);
+#else /* Old Style C */ 
+bool_t xdr_ypresp_val();
+#endif /* Old Style C */ 
+
+
+struct ypresp_key_val {
+       ypstat stat;
+       keydat key;
+       valdat val;
+};
+typedef struct ypresp_key_val ypresp_key_val;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresp_key_val(XDR *, ypresp_key_val*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresp_key_val(XDR *, ypresp_key_val*);
+#else /* Old Style C */ 
+bool_t xdr_ypresp_key_val();
+#endif /* Old Style C */ 
+
+
+struct ypresp_master {
+       ypstat stat;
+       peername peer;
+};
+typedef struct ypresp_master ypresp_master;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresp_master(XDR *, ypresp_master*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresp_master(XDR *, ypresp_master*);
+#else /* Old Style C */ 
+bool_t xdr_ypresp_master();
+#endif /* Old Style C */ 
+
+
+struct ypresp_order {
+       ypstat stat;
+       u_int32_t ordernum;
+};
+typedef struct ypresp_order ypresp_order;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresp_order(XDR *, ypresp_order*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresp_order(XDR *, ypresp_order*);
+#else /* Old Style C */ 
+bool_t xdr_ypresp_order();
+#endif /* Old Style C */ 
+
+
+struct ypresp_all {
+       bool_t more;
+       union {
+               ypresp_key_val val;
+       } ypresp_all_u;
+};
+typedef struct ypresp_all ypresp_all;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresp_all(XDR *, ypresp_all*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresp_all(XDR *, ypresp_all*);
+#else /* Old Style C */ 
+bool_t xdr_ypresp_all();
+#endif /* Old Style C */ 
+
+
+struct ypresp_xfr {
+       u_int transid;
+       ypxfrstat xfrstat;
+};
+typedef struct ypresp_xfr ypresp_xfr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresp_xfr(XDR *, ypresp_xfr*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresp_xfr(XDR *, ypresp_xfr*);
+#else /* Old Style C */ 
+bool_t xdr_ypresp_xfr();
+#endif /* Old Style C */ 
+
+
+struct ypmaplist {
+       mapname map;
+       struct ypmaplist *next;
+};
+typedef struct ypmaplist ypmaplist;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypmaplist(XDR *, ypmaplist*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypmaplist(XDR *, ypmaplist*);
+#else /* Old Style C */ 
+bool_t xdr_ypmaplist();
+#endif /* Old Style C */ 
+
+
+struct ypresp_maplist {
+       ypstat stat;
+       ypmaplist *maps;
+};
+typedef struct ypresp_maplist ypresp_maplist;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresp_maplist(XDR *, ypresp_maplist*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresp_maplist(XDR *, ypresp_maplist*);
+#else /* Old Style C */ 
+bool_t xdr_ypresp_maplist();
+#endif /* Old Style C */ 
+
+
+enum yppush_status {
+       YPPUSH_SUCC = 1,
+       YPPUSH_AGE = 2,
+       YPPUSH_NOMAP = -1,
+       YPPUSH_NODOM = -2,
+       YPPUSH_RSRC = -3,
+       YPPUSH_RPC = -4,
+       YPPUSH_MADDR = -5,
+       YPPUSH_YPERR = -6,
+       YPPUSH_BADARGS = -7,
+       YPPUSH_DBM = -8,
+       YPPUSH_FILE = -9,
+       YPPUSH_SKEW = -10,
+       YPPUSH_CLEAR = -11,
+       YPPUSH_FORCE = -12,
+       YPPUSH_XFRERR = -13,
+       YPPUSH_REFUSED = -14,
+};
+typedef enum yppush_status yppush_status;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_yppush_status(XDR *, yppush_status*);
+#elif defined(__STDC__)
+extern  bool_t xdr_yppush_status(XDR *, yppush_status*);
+#else /* Old Style C */ 
+bool_t xdr_yppush_status();
+#endif /* Old Style C */ 
+
+
+struct yppushresp_xfr {
+       u_int transid;
+       yppush_status status;
+};
+typedef struct yppushresp_xfr yppushresp_xfr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*);
+#elif defined(__STDC__)
+extern  bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*);
+#else /* Old Style C */ 
+bool_t xdr_yppushresp_xfr();
+#endif /* Old Style C */ 
+
+
+enum ypbind_resptype {
+       YPBIND_SUCC_VAL = 1,
+       YPBIND_FAIL_VAL = 2,
+};
+typedef enum ypbind_resptype ypbind_resptype;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypbind_resptype(XDR *, ypbind_resptype*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypbind_resptype(XDR *, ypbind_resptype*);
+#else /* Old Style C */ 
+bool_t xdr_ypbind_resptype();
+#endif /* Old Style C */ 
+
+
+struct ypbind_binding {
+       char ypbind_binding_addr[4];
+       char ypbind_binding_port[2];
+};
+typedef struct ypbind_binding ypbind_binding;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypbind_binding(XDR *, ypbind_binding*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypbind_binding(XDR *, ypbind_binding*);
+#else /* Old Style C */ 
+bool_t xdr_ypbind_binding();
+#endif /* Old Style C */ 
+
+
+struct ypbind_resp {
+       ypbind_resptype ypbind_status;
+       union {
+               u_int ypbind_error;
+               ypbind_binding ypbind_bindinfo;
+       } ypbind_resp_u;
+};
+typedef struct ypbind_resp ypbind_resp;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypbind_resp(XDR *, ypbind_resp*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypbind_resp(XDR *, ypbind_resp*);
+#else /* Old Style C */ 
+bool_t xdr_ypbind_resp();
+#endif /* Old Style C */ 
+
+#define YPBIND_ERR_ERR 1
+#define YPBIND_ERR_NOSERV 2
+#define YPBIND_ERR_RESC 3
+
+struct ypbind_setdom {
+       domainname ypsetdom_domain;
+       ypbind_binding ypsetdom_binding;
+       u_int ypsetdom_vers;
+};
+typedef struct ypbind_setdom ypbind_setdom;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypbind_setdom(XDR *, ypbind_setdom*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypbind_setdom(XDR *, ypbind_setdom*);
+#else /* Old Style C */ 
+bool_t xdr_ypbind_setdom();
+#endif /* Old Style C */ 
+
+
+#define YPPROG ((u_long)100004)
+#define YPVERS ((u_long)2)
+
+#ifdef __cplusplus
+#define YPPROC_NULL ((u_long)0)
+extern "C" void * ypproc_null_2(void *, CLIENT *);
+extern "C" void * ypproc_null_2_svc(void *, struct svc_req *);
+#define YPPROC_DOMAIN ((u_long)1)
+extern "C" bool_t * ypproc_domain_2(domainname *, CLIENT *);
+extern "C" bool_t * ypproc_domain_2_svc(domainname *, struct svc_req *);
+#define YPPROC_DOMAIN_NONACK ((u_long)2)
+extern "C" bool_t * ypproc_domain_nonack_2(domainname *, CLIENT *);
+extern "C" bool_t * ypproc_domain_nonack_2_svc(domainname *, struct svc_req *);
+#define YPPROC_MATCH ((u_long)3)
+extern "C" ypresp_val * ypproc_match_2(ypreq_key *, CLIENT *);
+extern "C" ypresp_val * ypproc_match_2_svc(ypreq_key *, struct svc_req *);
+#define YPPROC_FIRST ((u_long)4)
+extern "C" ypresp_key_val * ypproc_first_2(ypreq_nokey *, CLIENT *);
+extern "C" ypresp_key_val * ypproc_first_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_NEXT ((u_long)5)
+extern "C" ypresp_key_val * ypproc_next_2(ypreq_key *, CLIENT *);
+extern "C" ypresp_key_val * ypproc_next_2_svc(ypreq_key *, struct svc_req *);
+#define YPPROC_XFR ((u_long)6)
+extern "C" ypresp_xfr * ypproc_xfr_2(ypreq_xfr *, CLIENT *);
+extern "C" ypresp_xfr * ypproc_xfr_2_svc(ypreq_xfr *, struct svc_req *);
+#define YPPROC_CLEAR ((u_long)7)
+extern "C" void * ypproc_clear_2(void *, CLIENT *);
+extern "C" void * ypproc_clear_2_svc(void *, struct svc_req *);
+#define YPPROC_ALL ((u_long)8)
+extern "C" ypresp_all * ypproc_all_2(ypreq_nokey *, CLIENT *);
+extern "C" ypresp_all * ypproc_all_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_MASTER ((u_long)9)
+extern "C" ypresp_master * ypproc_master_2(ypreq_nokey *, CLIENT *);
+extern "C" ypresp_master * ypproc_master_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_ORDER ((u_long)10)
+extern "C" ypresp_order * ypproc_order_2(ypreq_nokey *, CLIENT *);
+extern "C" ypresp_order * ypproc_order_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_MAPLIST ((u_long)11)
+extern "C" ypresp_maplist * ypproc_maplist_2(domainname *, CLIENT *);
+extern "C" ypresp_maplist * ypproc_maplist_2_svc(domainname *, struct svc_req *);
+
+#elif defined(__STDC__)
+#define YPPROC_NULL ((u_long)0)
+extern  void * ypproc_null_2(void *, CLIENT *);
+extern  void * ypproc_null_2_svc(void *, struct svc_req *);
+#define YPPROC_DOMAIN ((u_long)1)
+extern  bool_t * ypproc_domain_2(domainname *, CLIENT *);
+extern  bool_t * ypproc_domain_2_svc(domainname *, struct svc_req *);
+#define YPPROC_DOMAIN_NONACK ((u_long)2)
+extern  bool_t * ypproc_domain_nonack_2(domainname *, CLIENT *);
+extern  bool_t * ypproc_domain_nonack_2_svc(domainname *, struct svc_req *);
+#define YPPROC_MATCH ((u_long)3)
+extern  ypresp_val * ypproc_match_2(ypreq_key *, CLIENT *);
+extern  ypresp_val * ypproc_match_2_svc(ypreq_key *, struct svc_req *);
+#define YPPROC_FIRST ((u_long)4)
+extern  ypresp_key_val * ypproc_first_2(ypreq_nokey *, CLIENT *);
+extern  ypresp_key_val * ypproc_first_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_NEXT ((u_long)5)
+extern  ypresp_key_val * ypproc_next_2(ypreq_key *, CLIENT *);
+extern  ypresp_key_val * ypproc_next_2_svc(ypreq_key *, struct svc_req *);
+#define YPPROC_XFR ((u_long)6)
+extern  ypresp_xfr * ypproc_xfr_2(ypreq_xfr *, CLIENT *);
+extern  ypresp_xfr * ypproc_xfr_2_svc(ypreq_xfr *, struct svc_req *);
+#define YPPROC_CLEAR ((u_long)7)
+extern  void * ypproc_clear_2(void *, CLIENT *);
+extern  void * ypproc_clear_2_svc(void *, struct svc_req *);
+#define YPPROC_ALL ((u_long)8)
+extern  ypresp_all * ypproc_all_2(ypreq_nokey *, CLIENT *);
+extern  ypresp_all * ypproc_all_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_MASTER ((u_long)9)
+extern  ypresp_master * ypproc_master_2(ypreq_nokey *, CLIENT *);
+extern  ypresp_master * ypproc_master_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_ORDER ((u_long)10)
+extern  ypresp_order * ypproc_order_2(ypreq_nokey *, CLIENT *);
+extern  ypresp_order * ypproc_order_2_svc(ypreq_nokey *, struct svc_req *);
+#define YPPROC_MAPLIST ((u_long)11)
+extern  ypresp_maplist * ypproc_maplist_2(domainname *, CLIENT *);
+extern  ypresp_maplist * ypproc_maplist_2_svc(domainname *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define YPPROC_NULL ((u_long)0)
+extern  void * ypproc_null_2();
+extern  void * ypproc_null_2_svc();
+#define YPPROC_DOMAIN ((u_long)1)
+extern  bool_t * ypproc_domain_2();
+extern  bool_t * ypproc_domain_2_svc();
+#define YPPROC_DOMAIN_NONACK ((u_long)2)
+extern  bool_t * ypproc_domain_nonack_2();
+extern  bool_t * ypproc_domain_nonack_2_svc();
+#define YPPROC_MATCH ((u_long)3)
+extern  ypresp_val * ypproc_match_2();
+extern  ypresp_val * ypproc_match_2_svc();
+#define YPPROC_FIRST ((u_long)4)
+extern  ypresp_key_val * ypproc_first_2();
+extern  ypresp_key_val * ypproc_first_2_svc();
+#define YPPROC_NEXT ((u_long)5)
+extern  ypresp_key_val * ypproc_next_2();
+extern  ypresp_key_val * ypproc_next_2_svc();
+#define YPPROC_XFR ((u_long)6)
+extern  ypresp_xfr * ypproc_xfr_2();
+extern  ypresp_xfr * ypproc_xfr_2_svc();
+#define YPPROC_CLEAR ((u_long)7)
+extern  void * ypproc_clear_2();
+extern  void * ypproc_clear_2_svc();
+#define YPPROC_ALL ((u_long)8)
+extern  ypresp_all * ypproc_all_2();
+extern  ypresp_all * ypproc_all_2_svc();
+#define YPPROC_MASTER ((u_long)9)
+extern  ypresp_master * ypproc_master_2();
+extern  ypresp_master * ypproc_master_2_svc();
+#define YPPROC_ORDER ((u_long)10)
+extern  ypresp_order * ypproc_order_2();
+extern  ypresp_order * ypproc_order_2_svc();
+#define YPPROC_MAPLIST ((u_long)11)
+extern  ypresp_maplist * ypproc_maplist_2();
+extern  ypresp_maplist * ypproc_maplist_2_svc();
+#endif /* Old Style C */ 
+
+#define YPPUSH_XFRRESPPROG ((u_long)0x40000000)
+#define YPPUSH_XFRRESPVERS ((u_long)1)
+
+#ifdef __cplusplus
+#define YPPUSHPROC_NULL ((u_long)0)
+extern "C" void * yppushproc_null_1(void *, CLIENT *);
+extern "C" void * yppushproc_null_1_svc(void *, struct svc_req *);
+#define YPPUSHPROC_XFRRESP ((u_long)1)
+extern "C" yppushresp_xfr * yppushproc_xfrresp_1(void *, CLIENT *);
+extern "C" yppushresp_xfr * yppushproc_xfrresp_1_svc(void *, struct svc_req *);
+
+#elif defined(__STDC__)
+#define YPPUSHPROC_NULL ((u_long)0)
+extern  void * yppushproc_null_1(void *, CLIENT *);
+extern  void * yppushproc_null_1_svc(void *, struct svc_req *);
+#define YPPUSHPROC_XFRRESP ((u_long)1)
+extern  yppushresp_xfr * yppushproc_xfrresp_1(void *, CLIENT *);
+extern  yppushresp_xfr * yppushproc_xfrresp_1_svc(void *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define YPPUSHPROC_NULL ((u_long)0)
+extern  void * yppushproc_null_1();
+extern  void * yppushproc_null_1_svc();
+#define YPPUSHPROC_XFRRESP ((u_long)1)
+extern  yppushresp_xfr * yppushproc_xfrresp_1();
+extern  yppushresp_xfr * yppushproc_xfrresp_1_svc();
+#endif /* Old Style C */ 
+
+#define YPBINDPROG ((u_long)100007)
+#define YPBINDVERS ((u_long)2)
+
+#ifdef __cplusplus
+#define YPBINDPROC_NULL ((u_long)0)
+extern "C" void * ypbindproc_null_2(void *, CLIENT *);
+extern "C" void * ypbindproc_null_2_svc(void *, struct svc_req *);
+#define YPBINDPROC_DOMAIN ((u_long)1)
+extern "C" ypbind_resp * ypbindproc_domain_2(domainname *, CLIENT *);
+extern "C" ypbind_resp * ypbindproc_domain_2_svc(domainname *, struct svc_req *);
+#define YPBINDPROC_SETDOM ((u_long)2)
+extern "C" void * ypbindproc_setdom_2(ypbind_setdom *, CLIENT *);
+extern "C" void * ypbindproc_setdom_2_svc(ypbind_setdom *, struct svc_req *);
+
+#elif defined(__STDC__)
+#define YPBINDPROC_NULL ((u_long)0)
+extern  void * ypbindproc_null_2(void *, CLIENT *);
+extern  void * ypbindproc_null_2_svc(void *, struct svc_req *);
+#define YPBINDPROC_DOMAIN ((u_long)1)
+extern  ypbind_resp * ypbindproc_domain_2(domainname *, CLIENT *);
+extern  ypbind_resp * ypbindproc_domain_2_svc(domainname *, struct svc_req *);
+#define YPBINDPROC_SETDOM ((u_long)2)
+extern  void * ypbindproc_setdom_2(ypbind_setdom *, CLIENT *);
+extern  void * ypbindproc_setdom_2_svc(ypbind_setdom *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define YPBINDPROC_NULL ((u_long)0)
+extern  void * ypbindproc_null_2();
+extern  void * ypbindproc_null_2_svc();
+#define YPBINDPROC_DOMAIN ((u_long)1)
+extern  ypbind_resp * ypbindproc_domain_2();
+extern  ypbind_resp * ypbindproc_domain_2_svc();
+#define YPBINDPROC_SETDOM ((u_long)2)
+extern  void * ypbindproc_setdom_2();
+extern  void * ypbindproc_setdom_2_svc();
+#endif /* Old Style C */ 
+
+#endif /* !_YP_H_RPCGEN */
diff --git a/ypserv.tproj/ypdb.c b/ypserv.tproj/ypdb.c
new file mode 100644 (file)
index 0000000..c9bd178
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ypdb.h"
+
+#ifdef YPDB_PATCH
+extern DBM *__hash_open();
+#else
+extern DBM *__bt_open();
+#endif
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+       char path[MAXPATHLEN];
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       char path[MAXPATHLEN];
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       db = (DBM *)__bt_open(path, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open_suf(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       return ((DBM *)__hash_open(file, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       db = (DBM *)__bt_open(file, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+extern void
+ypdb_close(db)
+       DBM *db;
+{
+       (void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_fetch(db, key)
+       DBM *db;
+       datum key;
+{
+       datum retval;
+       int status;
+
+       status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+       if (status) {
+               retval.dptr = NULL;
+               retval.dsize = 0;
+       }
+       return (retval);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_firstkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_nextkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_setkey(db, key)
+       DBM *db;
+        datum key;
+{
+       int status;
+       datum retdata;
+#ifdef YPDB_PATCH
+       datum retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       while ((retkey.dptr != NULL) &&
+              ((retkey.dsize != key.dsize) ||
+               (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) {
+         status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+         if (status)
+               retkey.dptr = NULL;
+       };
+       return (retkey);
+#else
+       status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR);
+       if (status)
+               key.dptr = NULL;
+       return (key);
+#endif
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ */
+
+int
+ypdb_delete(db, key)
+       DBM *db;
+       datum key;
+{
+       int status;
+
+       status = (db->del)(db, (DBT *)&key, 0);
+       if (status)
+               return (-1);
+       else
+               return (0);
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ *      1 if YPDB_INSERT and entry exists
+ */
+
+int
+ypdb_store(db, key, content, flags)
+       DBM *db;
+       datum key, content;
+       int flags;
+{
+       return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+           (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0));
+}
+
diff --git a/ypserv.tproj/ypdb.h b/ypserv.tproj/ypdb.h
new file mode 100644 (file)
index 0000000..45b0a7f
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDB_H_
+#define _YPDB_H_
+
+#ifndef _DB_H_
+#include <db.h>
+#endif
+
+#define YPDB_SUFFIX    ".db"
+
+/* Flags to ypdb_store(). */
+#define YPDB_INSERT      0
+#define YPDB_REPLACE     1
+
+#ifndef DATUM
+typedef struct {
+       char    *dptr;
+       int     dsize;
+} datum;
+#define DATUM
+#endif
+
+typedef DB DBM;
+
+__BEGIN_DECLS
+void    ypdb_close __P((DBM *));
+datum   ypdb_fetch __P((DBM *, datum));
+datum   ypdb_firstkey __P((DBM *));
+datum   ypdb_nextkey __P((DBM *));
+datum   ypdb_setkey __P((DBM *, datum));
+DBM     *ypdb_open __P((const char *, int, int));
+DBM     *ypdb_open_suf __P((const char *, int, int));
+int     ypdb_store __P((DBM *, datum, datum, int));
+__END_DECLS
+
+#endif /* !_YPDB_H_ */
diff --git a/ypserv.tproj/ypdef.h b/ypserv.tproj/ypdef.h
new file mode 100644 (file)
index 0000000..89970d7
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDEF_H_
+#define _YPDEF_H_
+
+#define YP_DB_PATH "/var/yp"
+#define YP_LAST_KEY        "YP_LAST_MODIFIED"
+#define YP_LAST_LEN       (sizeof(YP_LAST_KEY)-1)
+#define YP_INPUT_KEY       "YP_INPUT_FILE"
+#define YP_INPUT_LEN      (sizeof(YP_INPUT_KEY)-1)
+#define YP_OUTPUT_KEY      "YP_OUTPUT_FILE"
+#define YP_OUTPUT_LEN     (sizeof(YP_OUTPUT_KEY)-1)
+#define YP_MASTER_KEY      "YP_MASTER_NAME"
+#define YP_MASTER_LEN     (sizeof(YP_MASTER_KEY)-1)
+#define YP_DOMAIN_KEY      "YP_DOMAIN_NAME"
+#define YP_DOMAIN_LEN     (sizeof(YP_DOMAIN_KEY)-1)
+#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN"
+#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1)
+#define YP_SECURE_KEY      "YP_SECURE"
+#define YP_SECURE_LEN      (sizeof(YP_SECURE_KEY)-1)
+
+#define MAX_LAST_LEN 10
+#define MAX_MASTER_LEN 255
+#define YP_HOSTNAME "hosts.byname"
+#define YP_HOSTADDR "hosts.byaddr"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define YPXFR_PROC "/usr/sbin/ypxfr"
+#define YPPUSH_PROC "/usr/sbin/yppush"
+#define YPSERV_PID_PATH "/var/run/ypserv.pid"
+#define YP_SECURENET_FILE "/var/yp/securenet"
+
+#endif /* !_YPDEF_H_ */
diff --git a/ypserv.tproj/yplog.c b/ypserv.tproj/yplog.c
new file mode 100644 (file)
index 0000000..3460c9a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplog.c,v 1.5 1997/08/09 22:44:04 maja Exp $ */
+
+/*
+ * Copyright (c) 1996 Charles D. Cranor
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Charles D. Cranor.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * yplog.c: replacement yplog routines for 
+ * Mats O Jansson's ypserv program, as added by
+ * Chuck Cranor.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "yplog.h"
+
+static FILE    *logfp = NULL;          /* the log file */
+
+/*
+ * yplog(): like a printf, but to the log file.   does the flush
+ * and data for you.
+ */
+
+void
+#ifdef __STDC__
+yplog(const char *fmt, ...)
+#else
+yplog(fmt, va_alist)
+       char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+#ifdef __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       vyplog(fmt, ap);
+       va_end(ap);
+}
+
+/*
+ * vyplog() support routine for yplog()
+ */
+
+void
+vyplog(fmt, ap)
+       register const char *fmt;
+       va_list ap;
+{
+        time_t t;
+
+       if (logfp == NULL)
+               return;
+       (void)time(&t);
+       fprintf(logfp,"%.15s ", ctime(&t) + 4);
+       vfprintf(logfp, fmt, ap);
+       fprintf(logfp,"\n");
+       fflush(logfp);
+}
+
+/*
+ * open log
+ */
+
+void
+ypopenlog()
+{
+       static char logfn[] = "/var/yp/ypserv.log";
+
+       if (access(logfn, W_OK) == -1)
+               return;
+       logfp = fopen("/var/yp/ypserv.log", "a");
+       if (logfp == NULL)
+               return;
+       yplog("yplog opened");
+}
+
+/*
+ * close log
+ */
+
+void
+ypcloselog()
+{
+       if (logfp) {
+               yplog("yplog closed");
+               fclose(logfp);
+               logfp = NULL;
+       }
+}
diff --git a/ypserv.tproj/yplog.h b/ypserv.tproj/yplog.h
new file mode 100644 (file)
index 0000000..dd9d6fb
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplog.h,v 1.3 1996/05/30 09:53:04 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPLOG_H_
+#define _YPLOG_H_
+
+__BEGIN_DECLS
+void    yplog __P((const char *, ...));
+void    vyplog __P((const char *, _BSD_VA_LIST_));
+void   ypopenlog __P((void));
+void   ypcloselog __P((void));
+__END_DECLS
+
+#endif /* !_YPLOG_H_ */
diff --git a/ypserv.tproj/ypserv.acl b/ypserv.tproj/ypserv.acl
new file mode 100644 (file)
index 0000000..afeb86f
--- /dev/null
@@ -0,0 +1,44 @@
+# This is an example of an access control file to be used by ypserv.
+#
+# This file is parsed line by line. First match will terminate the check
+# of the caller.
+#
+
+#############################################################################
+# This is the commands that will match a single host
+#
+#      allow host <hostname|ip-address>
+#      deny host <hostname|ip-address>
+#
+# To process hostname gethostbyname is called. If the hostname has multiple
+# ip-addresses all will be added (I hope). ip-address is processed by
+# inet_aton.
+allow host localhost
+deny host jodie
+
+#############################################################################
+# This is the commands that will match a network
+#
+#      allow net <netname|netnumber> [netmask <netname|netnumber>]
+#      deny net <netname|netnumber> [netmask <netname|netnumber>]
+#
+# To process netname getnetbyname is called, and inet_aton is used for
+# netnumber. inet_aton both access numbers as 255.255.255.0 and 0xffffff00.
+#
+# If netmask isn't given the parser will assume netmask from the first bits
+# of the network number. So if the network is subneted the you have to add
+# the netmask. In my case I've got the network 139.58.253.0 at home so too
+# allow any of my computers to talk with the server I need the following line
+#
+allow net mojathome netmask 255.255.255.0
+
+#############################################################################
+# At last we have a command that will match any caller:
+#
+#      allow all 
+#      deny all
+#
+
+# reject all connections
+deny all
+
diff --git a/ypserv.tproj/ypserv.acl.5 b/ypserv.tproj/ypserv.acl.5
new file mode 100644 (file)
index 0000000..4e00b7b
--- /dev/null
@@ -0,0 +1,182 @@
+.\"    $OpenBSD: ypserv.acl.5,v 1.6 1997/08/05 09:26:56 maja Exp $
+.\" Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd July 2, 1994
+.Dt YPSERV.ACL 5
+.Os
+.Sh NAME
+.Nm ypserv.acl
+.Nd 
+.Xr ypserv 8
+configuration file
+.Sh DESCRIPTION
+The 
+.Nm ypserv.acl
+file controls which hosts can connect to the
+.Nm YP
+server.
+.Pp
+The format is more complex than the format for
+.Xr securenet 5 .
+The first two verbs on each line controls if the line will
+.Nm allow
+or
+.Nm deny
+access for a
+.Nm host ,
+network
+.Nm (net)
+or
+.Nm all
+hosts.
+.Pp
+The
+.Nm YP
+server reads the configuration file and build a list in memory. This list
+is processed from the beginning for every incomming request. As soon a
+match is found in the list the search terminates and it returns success
+or failure depending on 
+.Nm allow
+or 
+.Nm deny .
+If no match was found in the list success is returned.
+.Pp
+If access is denied every call will cause a 
+.Nm no such domain
+error for the caller.
+.Pp
+Don't forget to allow localhost access if you want the machine running
+.Nm ypserv
+access it too.
+.Pp
+There is no default name for this file. Start 
+.Nm ypserv
+with a
+.Ar -a filename
+to read a file with this format.
+.Pp
+The following different syntax can be used:
+.Pp
+<
+.Nm allow|deny
+>
+.Nm host
+<
+.Nm hostname|ip-address
+>
+.Pp
+If 
+.Nm hostname
+has more than one ip address then all will be added to the list.
+.Pp
+<
+.Nm allow|deny
+>
+.Nm net
+<
+.Nm netname|netnumber
+>
+.Op Nm netmask <netname|netnumber>
+.Pp
+If
+.Nm netmask
+part of the command isn't given then the netmask will be assumed to be a
+class A, B or C net depending on the net number.
+.Pp
+<
+.Nm allow|deny 
+>
+.Nm all
+.Pp
+A line containing one of these commands will always match any host.
+.Sh EXAMPLES
+.Pp
+A configuration file might appear as follows:
+.Bd -literal
+# This is an example of an access control file to be used by ypserv.
+#
+# This file is parsed line by line. First match will terminate the check
+# of the caller.
+#
+
+###########################################################################
+# This is the commands that will match a single host
+#
+#      allow host <hostname|ip-address>
+#      deny host <hostname|ip-address>
+#
+# To process hostname gethostbyname is called. If the hostname has
+# multiple ip-addresses all will be added (I hope). ip-address
+# processed by inet_aton.
+allow host localhost
+deny host jodie
+
+###########################################################################
+# This is the commands that will match a network
+#
+#      allow net <netname|netnumber> [netmask <netname|netnumber>]
+#      deny net <netname|netnumber> [netmask <netname|netnumber>]
+#
+# To process netname getnetbyname is called, and inet_aton is used for
+# netnumber. inet_aton both access numbers as 255.255.255.0 and 0xffffff00.
+#
+# If netmask isn't given the parser will assume netmask from the first bits
+# of the network number. So if the network is subneted the you have to add
+# the netmask. In my case I've got the network 139.58.253.0 at home so too
+# allow any of my computers to talk with the server I need the following
+# line
+#
+allow net mojathome netmask 255.255.255.0
+
+###########################################################################
+# At last we have a command that will match any caller:
+#
+#      allow all 
+#      deny all
+#
+
+# reject all connections
+deny all
+
+.Ed
+.Sh FILES
+.Bl -tag -width /var/yp/ypserv.acl -compact
+.It Pa /var/yp/ypserv.acl
+A
+.Xr ypserv 8
+configuration file.
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr ypserv 8 ,
+.Xr securenet 5
+.Sh AUTHOR
+Mats O Jansson <moj@stacken.kth.se>
+
diff --git a/ypserv.tproj/ypserv.c b/ypserv.tproj/ypserv.c
new file mode 100644 (file)
index 0000000..7089884
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $";
+#endif
+
+#include "yp.h"
+#include "ypv1.h"
+#include <stdio.h>
+#include <stdlib.h>/* getenv, exit */
+#include <rpc/pmap_clnt.h> /* for pmap_unset */
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ttycom.h>/* TIOCNOTTY */
+#ifdef __cplusplus
+#include <sysent.h> /* getdtablesize, open */
+#endif /* __cplusplus */
+#include <memory.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <syslog.h>
+#include "acl.h"
+#include "yplog.h"
+#include "ypdef.h"
+#include <sys/wait.h>
+#include <sys/ioctl.h> /* for ioctl */
+#include <sys/fcntl.h> /* for open */
+
+#ifdef __STDC__
+#define SIG_PF void(*)(int)
+#endif
+
+#ifdef DEBUG
+#define RPC_SVC_FG
+#endif
+
+#define _RPCSVC_CLOSEDOWN 120
+static int _rpcpmstart;                /* Started by a port monitor ? */
+static int _rpcfdtype;         /* Whether Stream or Datagram ? */
+static int _rpcsvcdirty;       /* Still serving ? */
+
+int    usedns = FALSE;
+char   *progname = "ypserv";
+char   *aclfile = NULL;
+
+void sig_child();
+void sig_hup();
+
+/* in the RPC library */
+SVCXPRT *svcfd_create(int, u_int, u_int);
+
+static
+void _msgout(char* msg)
+{
+#ifdef RPC_SVC_FG
+       if (_rpcpmstart)
+               syslog(LOG_ERR, msg);
+       else
+               (void) fprintf(stderr, "%s\n", msg);
+#else
+       syslog(LOG_ERR, msg);
+#endif
+}
+
+static void
+closedown()
+{
+       if (_rpcsvcdirty == 0) {
+               extern fd_set svc_fdset;
+               static int size;
+               int i, openfd;
+
+               if (_rpcfdtype == SOCK_DGRAM)
+                       exit(0);
+               if (size == 0) {
+                       size = getdtablesize();
+               }
+               for (i = 0, openfd = 0; i < size && openfd < 2; i++)
+                       if (FD_ISSET(i, &svc_fdset))
+                               openfd++;
+               if (openfd <= (_rpcpmstart?0:1))
+                       exit(0);
+       }
+       (void) alarm(_RPCSVC_CLOSEDOWN);
+}
+
+static void
+ypprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
+{
+       union {
+               domainname ypproc_domain_1_arg;
+               domainname ypproc_domain_nonack_1_arg;
+               yprequest ypproc_match_1_arg;
+               yprequest ypproc_first_1_arg;
+               yprequest ypproc_next_1_arg;
+               yprequest ypproc_poll_1_arg;
+               yprequest ypproc_push_1_arg;
+               yprequest ypproc_pull_1_arg;
+               yprequest ypproc_get_1_arg;
+       } argument;
+       char *result;
+       xdrproc_t xdr_argument, xdr_result;
+       char *(*local)(char *, struct svc_req *);
+
+       _rpcsvcdirty = 1;
+       switch (rqstp->rq_proc) {
+       case YPOLDPROC_NULL:
+               xdr_argument = (xdrproc_t) xdr_void;
+               xdr_result = (xdrproc_t) xdr_void;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_null_1_svc;
+               break;
+
+       case YPOLDPROC_DOMAIN:
+               xdr_argument = (xdrproc_t) xdr_domainname;
+               xdr_result = (xdrproc_t) xdr_bool;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_domain_1_svc;
+               break;
+
+       case YPOLDPROC_DOMAIN_NONACK:
+               xdr_argument = (xdrproc_t) xdr_domainname;
+               xdr_result = (xdrproc_t) xdr_bool;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_1_svc;
+               break;
+
+       case YPOLDPROC_MATCH:
+               xdr_argument = (xdrproc_t) xdr_yprequest;
+               xdr_result = (xdrproc_t) xdr_ypresponse;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_match_1_svc;
+               break;
+
+       case YPOLDPROC_FIRST:
+               xdr_argument = (xdrproc_t) xdr_yprequest;
+               xdr_result = (xdrproc_t) xdr_ypresponse;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_first_1_svc;
+               break;
+
+       case YPOLDPROC_NEXT:
+               xdr_argument = (xdrproc_t) xdr_yprequest;
+               xdr_result = (xdrproc_t) xdr_ypresponse;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_next_1_svc;
+               break;
+
+       case YPOLDPROC_POLL:
+               xdr_argument = (xdrproc_t) xdr_yprequest;
+               xdr_result = (xdrproc_t) xdr_ypresponse;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_poll_1_svc;
+               break;
+
+       case YPOLDPROC_PUSH:
+               xdr_argument = (xdrproc_t) xdr_yprequest;
+               xdr_result = (xdrproc_t) xdr_void;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_push_1_svc;
+               break;
+
+       case YPOLDPROC_PULL:
+               xdr_argument = (xdrproc_t) xdr_yprequest;
+               xdr_result = (xdrproc_t) xdr_void;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_pull_1_svc;
+               break;
+
+       case YPOLDPROC_GET:
+               xdr_argument = (xdrproc_t) xdr_yprequest;
+               xdr_result = (xdrproc_t) xdr_void;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_get_1_svc;
+               break;
+
+       default:
+               svcerr_noproc(transp);
+               _rpcsvcdirty = 0;
+               return;
+       }
+       (void) memset((char *)&argument, 0, sizeof (argument));
+       if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
+               svcerr_decode(transp);
+               _rpcsvcdirty = 0;
+               return;
+       }
+       result = (*local)((char *)&argument, rqstp);
+       if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+               svcerr_systemerr(transp);
+       }
+       if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
+               _msgout("unable to free arguments");
+               exit(1);
+       }
+       _rpcsvcdirty = 0;
+       return;
+}
+
+static void
+ypprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
+{
+       union {
+               domainname ypproc_domain_2_arg;
+               domainname ypproc_domain_nonack_2_arg;
+               ypreq_key ypproc_match_2_arg;
+               ypreq_nokey ypproc_first_2_arg;
+               ypreq_key ypproc_next_2_arg;
+               ypreq_xfr ypproc_xfr_2_arg;
+               ypreq_nokey ypproc_all_2_arg;
+               ypreq_nokey ypproc_master_2_arg;
+               ypreq_nokey ypproc_order_2_arg;
+               domainname ypproc_maplist_2_arg;
+       } argument;
+       char *result;
+       xdrproc_t xdr_argument, xdr_result;
+       char *(*local)(char *, struct svc_req *);
+
+       _rpcsvcdirty = 1;
+       switch (rqstp->rq_proc) {
+       case YPPROC_NULL:
+               xdr_argument = (xdrproc_t) xdr_void;
+               xdr_result = (xdrproc_t) xdr_void;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc;
+               break;
+
+       case YPPROC_DOMAIN:
+               xdr_argument = (xdrproc_t) xdr_domainname;
+               xdr_result = (xdrproc_t) xdr_bool;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc;
+               break;
+
+       case YPPROC_DOMAIN_NONACK:
+               xdr_argument = (xdrproc_t) xdr_domainname;
+               xdr_result = (xdrproc_t) xdr_bool;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc;
+               break;
+
+       case YPPROC_MATCH:
+               xdr_argument = (xdrproc_t) xdr_ypreq_key;
+               xdr_result = (xdrproc_t) xdr_ypresp_val;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc;
+               break;
+
+       case YPPROC_FIRST:
+               xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+               xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc;
+               break;
+
+       case YPPROC_NEXT:
+               xdr_argument = (xdrproc_t) xdr_ypreq_key;
+               xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc;
+               break;
+
+       case YPPROC_XFR:
+               xdr_argument = (xdrproc_t) xdr_ypreq_xfr;
+               xdr_result = (xdrproc_t) xdr_ypresp_xfr;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc;
+               break;
+
+       case YPPROC_CLEAR:
+               xdr_argument = (xdrproc_t) xdr_void;
+               xdr_result = (xdrproc_t) xdr_void;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc;
+               break;
+
+       case YPPROC_ALL:
+               xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+               xdr_result = (xdrproc_t) xdr_ypresp_all;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc;
+               break;
+
+       case YPPROC_MASTER:
+               xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+               xdr_result = (xdrproc_t) xdr_ypresp_master;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc;
+               break;
+
+       case YPPROC_ORDER:
+               xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+               xdr_result = (xdrproc_t) xdr_ypresp_order;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc;
+               break;
+
+       case YPPROC_MAPLIST:
+               xdr_argument = (xdrproc_t) xdr_domainname;
+               xdr_result = (xdrproc_t) xdr_ypresp_maplist;
+               local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc;
+               break;
+
+       default:
+               svcerr_noproc(transp);
+               _rpcsvcdirty = 0;
+               return;
+       }
+       (void) memset((char *)&argument, 0, sizeof (argument));
+       if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
+               svcerr_decode(transp);
+               _rpcsvcdirty = 0;
+               return;
+       }
+       result = (*local)((char *)&argument, rqstp);
+       if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+               svcerr_systemerr(transp);
+       }
+       if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
+               _msgout("unable to free arguments");
+               exit(1);
+       }
+       _rpcsvcdirty = 0;
+       return;
+}
+
+int
+main (argc,argv)
+int argc;
+char *argv[];
+{
+       register SVCXPRT *transp = NULL;
+       int sock;
+       int proto = 0;
+       struct sockaddr_in saddr;
+       int asize = sizeof (saddr);
+       int      usage = 0;
+       int      xflag = 0;
+       int      allowv1 = 0;
+       int      ch;
+       extern   char *optarg;
+       
+       while ((ch = getopt(argc, argv, "1a:dx")) != -1)
+               switch (ch) {
+               case '1':
+                       allowv1 = TRUE;
+                       break;
+               case 'a':
+                       aclfile = optarg;
+                       break;
+               case 'd':
+                       usedns = TRUE;
+                       break;
+               case 'x':
+                       xflag = TRUE;
+                       break;
+               default:
+                       usage++;
+                       break;
+               }
+       
+       if (usage) {
+               (void)fprintf(stderr,"usage: %s [-a aclfile] [-d] [-x]\n",progname);
+               exit(1);
+       }
+
+       if (geteuid() != 0) {
+               (void)fprintf(stderr,"%s: must be root to run.\n",progname);
+               exit(1);
+       }
+
+       if (aclfile != NULL) {
+               (void)acl_init(aclfile);
+       } else {
+               (void)acl_securenet(YP_SECURENET_FILE);
+       }
+       if (xflag) {
+               exit(1);
+       };
+
+       if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
+               int ssize = sizeof (int);
+
+               if (saddr.sin_family != AF_INET)
+                       exit(1);
+               if (getsockopt(0, SOL_SOCKET, SO_TYPE,
+                               (char *)&_rpcfdtype, &ssize) == -1)
+                       exit(1);
+               sock = 0;
+               _rpcpmstart = 1;
+               proto = 0;
+               openlog("ypserv", LOG_PID, LOG_DAEMON);
+       } else {
+#ifndef RPC_SVC_FG
+               int size;
+               int pid, i;
+
+               pid = fork();
+               if (pid < 0) {
+                       perror("cannot fork");
+                       exit(1);
+               }
+               if (pid)
+                       exit(0);
+               size = getdtablesize();
+               for (i = 0; i < size; i++)
+                       (void) close(i);
+               i = open("/dev/console", 2);
+               (void) dup2(i, 1);
+               (void) dup2(i, 2);
+               i = open("/dev/tty", 2);
+               if (i >= 0) {
+                       (void) ioctl(i, TIOCNOTTY, (char *)NULL);
+                       (void) close(i);
+               }
+               openlog("ypserv", LOG_PID, LOG_DAEMON);
+#endif
+               sock = RPC_ANYSOCK;
+               (void) pmap_unset(YPPROG, YPVERS);
+               (void) pmap_unset(YPPROG, YPOLDVERS);
+       }
+
+       ypopenlog();    /* open log file */
+       ypdb_init();    /* init db stuff */
+
+       chdir("/");
+       
+       (void)signal(SIGCHLD, sig_child);
+       (void)signal(SIGHUP, sig_hup);
+       { FILE *pidfile = fopen(YPSERV_PID_PATH, "w");
+         if (pidfile != NULL) {
+               fprintf(pidfile, "%d\n", getpid());
+               fclose(pidfile);
+         }
+       }
+
+       if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
+               transp = svcudp_create(sock);
+               if (transp == NULL) {
+                       _msgout("cannot create udp service.");
+                       exit(1);
+               }
+               if (transp->xp_port >= IPPORT_RESERVED) {
+                       _msgout("cannot allocate udp privileged port.");
+                       exit(1);
+               }
+               if (!_rpcpmstart)
+                       proto = IPPROTO_UDP;
+               if (allowv1) {
+                       if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
+                               _msgout("unable to register (YPPROG, YPOLDVERS, udp).");
+                               exit(1);
+                       }
+               }
+               if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
+                       _msgout("unable to register (YPPROG, YPVERS, udp).");
+                       exit(1);
+               }
+       }
+
+       if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
+               if (_rpcpmstart)
+                       transp = svcfd_create(sock, 0, 0);
+               else
+                       transp = svctcp_create(sock, 0, 0);
+               if (transp == NULL) {
+                       _msgout("cannot create tcp service.");
+                       exit(1);
+               }
+               if (transp->xp_port >= IPPORT_RESERVED) {
+                       _msgout("cannot allocate tcp privileged port.");
+                       exit(1);
+               }
+               if (!_rpcpmstart)
+                       proto = IPPROTO_TCP;
+               if (allowv1) {
+                       if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
+                               _msgout("unable to register (YPPROG, YPOLDVERS, tcp).");
+                               exit(1);
+                       }
+               }
+               if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
+                       _msgout("unable to register (YPPROG, YPVERS, tcp).");
+                       exit(1);
+               }
+       }
+
+       if (transp == (SVCXPRT *)NULL) {
+               _msgout("could not create a handle");
+               exit(1);
+       }
+       if (_rpcpmstart) {
+               (void) signal(SIGALRM, (SIG_PF) closedown);
+               (void) alarm(_RPCSVC_CLOSEDOWN);
+       }
+       svc_run();
+       _msgout("svc_run returned");
+       exit(1);
+       /* NOTREACHED */
+}
+
+void
+sig_child()
+{
+       int save_errno = errno;
+
+       while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0)
+               ;
+       errno = save_errno;
+}
+
+void
+sig_hup()
+{
+       acl_reset();
+       if (aclfile != NULL) {
+               yplog("sig_hup: reread %s",aclfile);
+               (void)acl_init(aclfile);
+       } else {
+               yplog("sig_hup: reread %s",YP_SECURENET_FILE);
+               (void)acl_securenet(YP_SECURENET_FILE);
+       }
+}
diff --git a/ypserv.tproj/ypserv_db.c b/ypserv.tproj/ypserv_db.c
new file mode 100644 (file)
index 0000000..b7b6469
--- /dev/null
@@ -0,0 +1,811 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * Copyright (c) 1996 Charles D. Cranor
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ *     and Charles D. Cranor.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $";
+#endif
+
+/*
+ * major revision/cleanup of Mats' version 
+ * done by Chuck Cranor <chuck@ccrc.wustl.edu>
+ * Jan 1996.
+ */
+
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <sys/errno.h>
+#include "yplog.h"
+#include "ypdb.h"
+#include "ypdef.h"
+
+LIST_HEAD(domainlist, opt_domain);     /* LIST of domains */
+LIST_HEAD(maplist, opt_map);           /* LIST of maps (in a domain) */
+CIRCLEQ_HEAD(mapq, opt_map);           /* CIRCLEQ of maps (LRU) */
+
+struct opt_map {
+       mapname map;                    /* map name (malloc'd) */
+       DBM     *db;                    /* database */
+       struct opt_domain *dom;         /* back ptr to our domain */
+       int     host_lookup;            /* host lookup */
+       int     secure;                 /* secure map? */
+       CIRCLEQ_ENTRY(opt_map) mapsq;   /* map queue pointers */
+       LIST_ENTRY(opt_map) mapsl;      /* map list pointers */
+};
+
+struct opt_domain {
+       domainname      domain;         /* domain name (malloc'd) */
+       struct maplist  dmaps;          /* the domain's active maps */
+       LIST_ENTRY(opt_domain) domsl;   /* global linked list of domains */
+};
+
+
+struct domainlist doms;                        /* global list of domains */
+struct mapq maps;                      /* global queue of maps (LRU) */
+
+extern int usedns;
+
+/*
+ * ypdb_init: init the queues and lists
+ */
+
+void
+ypdb_init()
+
+{
+       LIST_INIT(&doms);
+       CIRCLEQ_INIT(&maps);
+}
+
+
+/*
+ * yp_private:
+ * Check if key is a YP private key. Return TRUE if it is and
+ * ypprivate is FALSE.
+ */
+
+int
+yp_private(key,ypprivate)
+       datum   key;
+       int     ypprivate;
+{
+/*     int     result; */
+
+       if (ypprivate)
+           return (FALSE);
+
+       if (key.dsize == 0 || key.dptr == NULL)
+               return (FALSE);
+
+       if (key.dsize == YP_LAST_LEN &&
+           strncmp(key.dptr,YP_LAST_KEY,YP_LAST_LEN) == 0)
+               return(TRUE);
+       if (key.dsize == YP_INPUT_LEN &&
+           strncmp(key.dptr,YP_INPUT_KEY,YP_INPUT_LEN) == 0)
+               return(TRUE);
+       if (key.dsize == YP_OUTPUT_LEN &&
+           strncmp(key.dptr,YP_OUTPUT_KEY,YP_OUTPUT_LEN) == 0)
+               return(TRUE);
+       if (key.dsize == YP_MASTER_LEN &&
+           strncmp(key.dptr,YP_MASTER_KEY,YP_MASTER_LEN) == 0)
+               return(TRUE);
+       if (key.dsize == YP_DOMAIN_LEN &&
+           strncmp(key.dptr,YP_DOMAIN_KEY,YP_DOMAIN_LEN) == 0)
+               return(TRUE);
+       if (key.dsize == YP_INTERDOMAIN_LEN &&
+           strncmp(key.dptr,YP_INTERDOMAIN_KEY,YP_INTERDOMAIN_LEN) == 0)
+               return(TRUE);
+       if (key.dsize == YP_SECURE_LEN &&
+           strncmp(key.dptr,YP_SECURE_KEY,YP_SECURE_LEN) == 0)
+               return(TRUE);
+       
+       return(FALSE);
+}     
+
+/*
+ * Close least recent used map. This routine is called when we have
+ * no more file descripotors free, or we want to close all maps.
+ */
+
+void
+ypdb_close_last()
+{
+       struct opt_map *last = maps.cqh_last;
+
+       if (last == (void*)&maps) {
+               yplog("  ypdb_close_last: LRU list is empty!");
+               return;
+       }
+
+       CIRCLEQ_REMOVE(&maps, last, mapsq);     /* remove from LRU circleq */
+       LIST_REMOVE(last, mapsl);               /* remove from domain list */
+
+#ifdef DEBUG
+       yplog("  ypdb_close_last: closing map %s in domain %s [db=0x%x]",
+               last->map, last->dom->domain, last->db);
+#endif
+
+       ypdb_close(last->db);                   /* close DB */
+       free(last->map);                        /* free map name */
+       free(last);                             /* free map */
+
+       
+}
+
+/*
+ * Close all open maps.
+ */
+
+void
+ypdb_close_all()
+{
+       
+#ifdef DEBUG
+       yplog("  ypdb_close_all(): start");
+#endif
+       while (maps.cqh_first != (void *)&maps) {
+               ypdb_close_last();
+       }
+#ifdef DEBUG
+       yplog("  ypdb_close_all(): done");
+#endif
+}
+
+/*
+ * Close Database if Open/Close Optimization isn't turned on.
+ */
+
+void
+ypdb_close_db(db)
+       DBM     *db;
+{
+#ifdef DEBUG
+       yplog("  ypdb_close_db(0x%x)", db);
+#endif
+#ifndef OPTDB
+       ypdb_close_all();
+#endif
+}
+
+/*
+ * ypdb_open_db
+ */
+
+DBM *
+ypdb_open_db(domain, map, status, map_info)
+       domainname      domain;
+       mapname         map;
+       ypstat          *status;
+       struct opt_map  **map_info;
+{
+       char map_path[MAXPATHLEN];
+       static char   *domain_key = YP_INTERDOMAIN_KEY;
+       static char   *secure_key = YP_SECURE_KEY;
+/*     struct  stat finfo; */
+       DBM     *db;
+/*     int     fd; */
+       struct opt_domain *d = NULL;
+       struct opt_map  *m = NULL;
+       datum   k,v;
+#ifdef OPTDB
+       int     i;
+#endif
+       /*
+        * check for preloaded domain, map
+        */
+
+       for (d = doms.lh_first ; d != NULL ; d = d->domsl.le_next) {
+               if (strcmp(domain, d->domain) == 0) break;
+       }
+
+       if (d) {
+               for (m = d->dmaps.lh_first ; m != NULL ; m = m->mapsl.le_next)
+                       if (strcmp(map, m->map) == 0) break;
+       }
+
+       /*
+        * map found open?
+        */
+
+       if (m) {
+#ifdef DEBUG
+               yplog("  ypdb_open_db: cached open: domain=%s, map=%s, db=0x%x",
+                       domain, map, m->db);
+#endif
+               CIRCLEQ_REMOVE(&maps, m, mapsq);        /* adjust LRU queue */
+               CIRCLEQ_INSERT_HEAD(&maps, m, mapsq);
+               *status = YP_TRUE;
+               return(m->db);
+       }
+
+       /* Check for illegal charcaters */
+
+       if (strchr(domain, '/')) {
+               *status = YP_NODOM;
+               return (NULL);
+       }
+       if (strchr(map, '/')) {
+               *status = YP_NOMAP;
+               return (NULL);
+       }
+
+
+       /*
+        * open map
+        */
+#ifdef OPTDB
+       i = 0;
+       while (i == 0) {
+#endif
+               snprintf(map_path, sizeof(map_path), "%s/%s/%s", YP_DB_PATH, 
+                        domain, map);
+               db = ypdb_open(map_path, O_RDONLY, 0444);
+#ifdef OPTDB
+               if (db == NULL) {
+#ifdef DEBUG
+                       yplog("  ypdb_open_db: errno %d (%s)",
+                       errno,sys_errlist[errno]);
+#endif
+                       if ((errno == ENFILE) || (errno == EMFILE)) {
+                               ypdb_close_last();
+                       } else {
+                               i = errno;
+                       }
+               } else {
+                       i = 4711;
+               }
+       };
+#endif
+       *status = YP_NOMAP;             /* see note below */
+       if (db == NULL) {
+               if (errno == ENOENT) {
+#ifdef DEBUG
+                       yplog("  ypdb_open_db: no map %s (domain=%s)",
+                             map, domain);
+#endif
+                       return(NULL);
+               }
+#ifdef DEBUG
+               yplog("  ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)", 
+                       map, domain);
+#endif
+               return(NULL);
+       }
+       
+       /*
+        * note: status now YP_NOMAP
+        */
+
+       if (d == NULL) {                /* allocate new domain? */
+               d = (struct opt_domain *) malloc(sizeof(*d));
+               if (d) d->domain = strdup(domain);
+               if (d == NULL || d->domain == NULL) {
+                       yplog("  ypdb_open_db: MALLOC failed");
+                       ypdb_close(db);
+                       if (d) free(d);
+                       return(NULL);
+               }
+               LIST_INIT(&d->dmaps);
+               LIST_INSERT_HEAD(&doms, d, domsl);
+#ifdef DEBUG
+               yplog("  ypdb_open_db: NEW DOMAIN %s", domain);
+#endif
+       }
+
+       /*
+        * m must be NULL since we couldn't find a map.  allocate new one
+        */
+
+       m = (struct opt_map *) malloc(sizeof(*m));
+       if (m) {
+               m->map = strdup(map);
+       }
+       if (m == NULL || m->map == NULL) {
+               if (m) free(m);
+               yplog("  ypdb_open_db: MALLOC failed");
+               ypdb_close(db);
+               return(NULL);
+       }
+       m->db = db;
+       m->dom = d;
+       m->host_lookup = FALSE;
+       CIRCLEQ_INSERT_HEAD(&maps, m, mapsq);
+       LIST_INSERT_HEAD(&d->dmaps, m, mapsl);
+       if (strcmp(map, YP_HOSTNAME) == 0 || strcmp(map, YP_HOSTADDR) == 0) {
+               if (!usedns) {
+                       k.dptr = domain_key;
+                       k.dsize = YP_INTERDOMAIN_LEN;
+                       v = ypdb_fetch(db,k);
+                       if (v.dptr) m->host_lookup = TRUE;
+               } else {
+                       m->host_lookup = TRUE;
+               }
+       }
+       m->secure = FALSE;
+       k.dptr = secure_key;
+       k.dsize = YP_SECURE_LEN;
+       v = ypdb_fetch(db,k);
+       if (v.dptr) m->secure = TRUE;
+       *status = YP_TRUE;
+       if (map_info) *map_info = m;
+#ifdef DEBUG
+            yplog("  ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=0x%x", 
+                       domain, map, m->host_lookup, m->secure, m->db);
+#endif
+       return(m->db);
+}
+
+#if 0
+/*
+ * lookup host. Not needed for Rhapsody, lookupd does this stuff.
+ */
+
+ypstat
+lookup_host(nametable, host_lookup, db, keystr, result)
+       int     nametable;
+       int     host_lookup;
+       DBM     *db;
+       char    *keystr;
+       ypresp_val *result;
+{
+       struct  hostent *host;
+       struct  in_addr *addr_name;
+       struct  in_addr addr_addr;
+       static  char val[BUFSIZ+1]; /* match libc */
+       static  hostname[MAXHOSTNAMELEN];
+       char    tmpbuf[MAXHOSTNAMELEN + 20];
+       char *v;
+       int l;
+       char    *ptr;
+       
+       if (!host_lookup) return(YP_NOKEY);
+
+       if ((_res.options & RES_INIT) == 0)
+               res_init();
+       bcopy("b", _res.lookups, sizeof("b"));
+
+       if (nametable) {
+               host = gethostbyname(keystr);
+               if (host == NULL || host->h_addrtype != AF_INET) 
+                       return(YP_NOKEY);
+               addr_name = (struct in_addr *) *host->h_addr_list;
+               v = val;
+               for (; host->h_addr_list[0] != NULL; host->h_addr_list++) {
+                       addr_name = (struct in_addr *)host->h_addr_list[0];
+                       snprintf(tmpbuf,sizeof(tmpbuf), "%s %s\n",
+                               inet_ntoa(*addr_name), host->h_name);
+                       if (v - val + strlen(tmpbuf) + 1 > sizeof(val))
+                               break;
+                       strcpy(v, tmpbuf);
+                       v = v + strlen(tmpbuf);
+               }
+               result->val.valdat_val = val;
+               result->val.valdat_len = v - val;
+               return(YP_TRUE);
+       }
+
+       inet_aton(keystr, &addr_addr);
+       host = gethostbyaddr((char *) &addr_addr, sizeof(addr_addr), AF_INET);
+       if (host == NULL) return(YP_NOKEY);
+
+       strncpy((char *)hostname, host->h_name, sizeof(hostname) - 1);
+       hostname[sizeof(hostname) - 1] = '\0';
+       host = gethostbyname((char *)hostname);
+       if (host == NULL) return(YP_NOKEY);
+
+       l = 0;
+       for(; host->h_addr_list[0] != NULL; host->h_addr_list++)
+               if (!bcmp(host->h_addr_list[0], &addr_addr, sizeof(addr_addr)))
+                       l++;
+       if (l == 0) {
+               yplog("lookup_host: address %s not listed for host %s\n",
+                      inet_ntoa(addr_addr), hostname);
+               syslog(LOG_NOTICE,
+                      "ypserv: address %s not listed for host %s\n",
+                      inet_ntoa(addr_addr), hostname);
+               return(YP_NOKEY);
+       }
+
+       snprintf(val,sizeof(val),"%s %s",keystr,host->h_name);
+       l = strlen(val);
+       v = val + l;
+       while ((ptr = *(host->h_aliases)) != NULL) {
+               l = strlen(ptr);
+               if ((v - val) + l + 1 > BUFSIZ)
+                       break;
+               strcpy(v, " ");
+               v += 1;
+               strcpy(v, ptr);
+               v += l;
+               host->h_aliases++;
+       }
+       result->val.valdat_val = val;
+       result->val.valdat_len = v - val;
+
+       return(YP_TRUE);
+}
+#endif 
+
+ypresp_val
+ypdb_get_record(domain, map, key, ypprivate)
+       domainname      domain;
+       mapname         map;
+       keydat          key;
+       int             ypprivate;
+{
+       static  ypresp_val res;
+/*     static  char keystr[YPMAXRECORD+1]; */
+       DBM     *db;
+       datum   k,v;
+       int     host_lookup;
+       struct opt_map *map_info = NULL;
+
+       bzero((char *)&res, sizeof(res));
+       
+       db = ypdb_open_db(domain, map, &res.stat, &map_info);
+       if (!db || res.stat < 0) 
+               return(res);
+       if (map_info)
+               host_lookup = map_info->host_lookup;
+
+       k.dptr = key.keydat_val;
+       k.dsize = key.keydat_len;
+       
+       if (yp_private(k,ypprivate)) {
+               res.stat = YP_NOKEY;
+               goto done;
+       }
+
+       v = ypdb_fetch(db, k);
+
+       /* lookupd does DNS resolution, not ypserv. */
+       if (v.dptr == NULL) {
+               res.stat = YP_NOKEY;
+               res.val.valdat_val = NULL;
+               res.val.valdat_len = 0;
+       } else {
+               res.val.valdat_val = v.dptr;
+               res.val.valdat_len = v.dsize;
+       }
+
+done:
+       ypdb_close_db(db);
+       return(res);
+       
+}
+
+ypresp_key_val
+ypdb_get_first(domain, map, ypprivate)
+       domainname domain;
+       mapname map;
+       int ypprivate;
+{
+       static ypresp_key_val res;
+       DBM     *db;
+       datum   k,v;
+
+       bzero((char *)&res, sizeof(res));
+       
+       db = ypdb_open_db(domain, map, &res.stat, NULL);
+
+       if (res.stat >= 0) {
+
+         k = ypdb_firstkey(db);
+         
+         while (yp_private(k,ypprivate)) {
+           k = ypdb_nextkey(db);
+         };
+         
+         if (k.dptr == NULL) {
+           res.stat = YP_NOKEY;
+         } else {
+           res.key.keydat_val = k.dptr;
+           res.key.keydat_len = k.dsize;
+           v = ypdb_fetch(db,k);
+           if (v.dptr == NULL) {
+             res.stat = YP_NOKEY;
+           } else {
+             res.val.valdat_val = v.dptr;
+             res.val.valdat_len = v.dsize;
+           }
+         }
+       }
+
+       ypdb_close_db(db);
+       
+       return (res);
+}
+
+ypresp_key_val
+ypdb_get_next(domain, map, key, ypprivate)
+       domainname domain;
+       mapname map;
+       keydat key;
+       int ypprivate;
+{
+       static ypresp_key_val res;
+       DBM     *db;
+       datum   k,v,n;
+
+       bzero((char *)&res, sizeof(res));
+       
+       db = ypdb_open_db(domain, map, &res.stat, NULL);
+       
+       if (res.stat >= 0) {
+
+         n.dptr = key.keydat_val;
+         n.dsize = key.keydat_len;
+         v.dptr = NULL;
+         v.dsize = 0;
+         k.dptr = NULL;
+         k.dsize = 0;
+
+         n = ypdb_setkey(db,n);
+
+         if (n.dptr != NULL) {
+           k = ypdb_nextkey(db);
+         } else {
+           k.dptr = NULL;
+         };
+
+         if (k.dptr != NULL) {
+           while (yp_private(k,ypprivate)) {
+             k = ypdb_nextkey(db);
+           };
+         };
+
+         if (k.dptr == NULL) {
+           res.stat = YP_NOMORE;
+         } else {
+           res.key.keydat_val = k.dptr;
+           res.key.keydat_len = k.dsize;
+           v = ypdb_fetch(db,k);
+           if (v.dptr == NULL) {
+             res.stat = YP_NOMORE;
+           } else {
+             res.val.valdat_val = v.dptr;
+             res.val.valdat_len = v.dsize;
+           }
+         }
+       }
+
+       ypdb_close_db(db);
+       
+       return (res);
+}
+
+ypresp_order
+ypdb_get_order(domain, map)
+       domainname domain;
+       mapname map;
+{
+       static ypresp_order res;
+       static char   *order_key = YP_LAST_KEY;
+       char   order[MAX_LAST_LEN+1];
+       DBM     *db;
+       datum   k,v;
+
+       bzero((char *)&res, sizeof(res));
+       
+       db = ypdb_open_db(domain, map, &res.stat, NULL);
+       
+       if (res.stat >= 0) {
+
+         k.dptr = order_key;
+         k.dsize = YP_LAST_LEN;
+
+         v = ypdb_fetch(db,k);
+         if (v.dptr == NULL) {
+           res.stat = YP_NOKEY;
+         } else {
+           strncpy(order, v.dptr, v.dsize);
+           order[v.dsize] = '\0';
+           res.ordernum = (u_int32_t)atol(order);
+         }
+       }
+
+       ypdb_close_db(db);
+       
+       return (res);
+}
+
+ypresp_master
+ypdb_get_master(domain, map)
+       domainname domain;
+       mapname map;
+{
+       static ypresp_master res;
+       static char   *master_key = YP_MASTER_KEY;
+       static char   master[MAX_MASTER_LEN+1];
+       DBM     *db;
+       datum   k,v;
+
+       bzero((char *)&res, sizeof(res));
+       
+       db = ypdb_open_db(domain, map, &res.stat, NULL);
+       
+       if (res.stat >= 0) {
+
+         k.dptr = master_key;
+         k.dsize = YP_MASTER_LEN;
+
+         v = ypdb_fetch(db,k);
+         if (v.dptr == NULL) {
+           res.stat = YP_NOKEY;
+         } else {
+           strncpy(master, v.dptr, v.dsize);
+           master[v.dsize] = '\0';
+           res.peer = (peername) &master;
+         }
+       }
+
+       ypdb_close_db(db);
+       
+       return (res);
+}
+
+bool_t
+ypdb_xdr_get_all(xdrs, req)
+       XDR *xdrs;
+       ypreq_nokey *req;
+{
+       static ypresp_all resp;
+       DBM     *db;
+       datum   k,v;
+
+       bzero((char *)&resp, sizeof(resp));
+       
+       /*
+        * open db, and advance past any private keys we may see
+        */
+
+       db = ypdb_open_db(req->domain, req->map, 
+                       &resp.ypresp_all_u.val.stat, NULL);
+       if (!db || resp.ypresp_all_u.val.stat < 0) 
+               return(FALSE);
+       k = ypdb_firstkey(db);
+       while (yp_private(k,FALSE)) {
+               k = ypdb_nextkey(db);
+       };
+       
+       while(1) {
+               
+               if (k.dptr == NULL) 
+                       break;
+
+               v = ypdb_fetch(db,k);
+
+               if (v.dptr == NULL) 
+                       break;
+
+               resp.more = TRUE;
+               resp.ypresp_all_u.val.stat = YP_TRUE;
+               resp.ypresp_all_u.val.key.keydat_val = k.dptr;
+               resp.ypresp_all_u.val.key.keydat_len = k.dsize;
+               resp.ypresp_all_u.val.val.valdat_val = v.dptr;
+               resp.ypresp_all_u.val.val.valdat_len = v.dsize;
+                       
+               if (!xdr_ypresp_all(xdrs, &resp)) {
+#ifdef DEBUG
+                       yplog("  ypdb_xdr_get_all: xdr_ypresp_all failed");
+#endif                                 
+                       return(FALSE);
+               }
+                       
+               /* advance past private keys */
+               k = ypdb_nextkey(db);
+               while (yp_private(k,FALSE)) {
+                       k = ypdb_nextkey(db);
+               }
+       }
+               
+       bzero((char *)&resp, sizeof(resp));
+       resp.ypresp_all_u.val.stat = YP_NOKEY;
+       resp.more = FALSE;
+       
+       if (!xdr_ypresp_all(xdrs, &resp)) {
+#ifdef DEBUG
+               yplog("  ypdb_xdr_get_all: final xdr_ypresp_all failed");
+#endif
+               return(FALSE);
+       }
+               
+       ypdb_close_db(db);
+       
+       return (TRUE);
+}
+
+int
+ypdb_secure(domain, map)
+       domainname      domain;
+       mapname         map;
+{
+       static  ypresp_val res;
+       DBM     *db;
+       int     secure;
+       struct opt_map *map_info = NULL;
+
+       bzero((char *)&res, sizeof(res));
+       secure = FALSE;
+
+       db = ypdb_open_db(domain, map, &res.stat, &map_info);
+       if (!db || res.stat < 0) 
+               return(secure);                 /* ? */
+       if (map_info)
+               secure = map_info->secure;
+
+       ypdb_close_db(db);
+       return(secure);
+}
+
diff --git a/ypserv.tproj/ypserv_proc.c b/ypserv.tproj/ypserv_proc.c
new file mode 100644 (file)
index 0000000..84accf6
--- /dev/null
@@ -0,0 +1,1061 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypserv_proc.c,v 1.14 1997/09/12 01:44:57 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: ypserv_proc.c,v 1.14 1997/09/12 01:44:57 deraadt Exp $";
+#endif
+
+#include <rpc/rpc.h>
+#include "yp.h"
+#include "ypv1.h"
+#include <rpcsvc/ypclnt.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "ypdb.h"
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "yplog.h"
+#include "ypdef.h"
+
+#ifdef DEBUG
+#define YPLOG yplog
+#else /* DEBUG */
+#define YPLOG if (!ok) yplog
+#endif /* DEBUG */
+
+extern ypresp_val ypdb_get_record();
+extern ypresp_key_val ypdb_get_first();
+extern ypresp_key_val ypdb_get_next();
+extern ypresp_order ypdb_get_order();
+extern ypresp_master ypdb_get_master();
+extern bool_t ypdb_xdr_get_all();
+extern void ypdb_close_all();
+extern int ypdb_secure();
+
+static char *True = "true";
+static char *False = "FALSE";
+#define TORF(N) ((N) ? True : False)
+void *
+ypproc_null_2_svc(argp, rqstp)
+       void *argp;
+        struct svc_req *rqstp;
+{
+       static char *result;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+
+       YPLOG("null_2: caller=[%s].%d, auth_ok=%s",
+             inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok));
+
+       if (!ok) {
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       result = NULL;
+
+       return ((void *)&result);
+}
+
+bool_t *
+ypproc_domain_2_svc(argp, rqstp)
+       domainname *argp;
+        struct svc_req *rqstp;
+{
+       static bool_t result; /* is domain_served? */
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       static char domain_path[MAXPATHLEN];
+       struct stat finfo;
+
+       if (strchr(*argp, '/'))
+               goto bail;
+       snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
+       result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
+                                   (finfo.st_mode & S_IFDIR));
+
+       YPLOG("domain_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
+             inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), 
+             TORF(ok), *argp, TORF(result));
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       return (&result);
+}
+
+bool_t *
+ypproc_domain_nonack_2_svc(argp, rqstp)
+       domainname *argp;
+        struct svc_req *rqstp;
+{
+       static bool_t result; /* is domain served? */
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       static char domain_path[MAXPATHLEN];
+       struct stat finfo;
+
+       if (strchr(*argp, '/'))
+               goto bail;
+       snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
+       result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
+                                   (finfo.st_mode & S_IFDIR));
+
+       YPLOG(
+         "domain_nonack_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), 
+         *argp, TORF(result));
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (!result) {
+               return(NULL); /* don't send nack */
+       }
+
+       return (&result);
+}
+
+ypresp_val *
+ypproc_match_2_svc(argp, rqstp)
+       ypreq_key *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_val res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure = ypdb_secure(argp->domain,argp->map);
+
+       if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
+               goto bail;
+       YPLOG(
+         "match_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.stat = YP_YPERR;
+       } else {
+               res = ypdb_get_record(argp->domain,argp->map,argp->key, FALSE);
+       }
+
+#ifdef DEBUG
+       yplog("  match2_status: %s", yperr_string(ypprot_err(res.stat)));
+#endif
+
+       return (&res);
+}
+
+ypresp_key_val *
+ypproc_first_2_svc(argp, rqstp)
+       ypreq_nokey *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_key_val res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure = ypdb_secure(argp->domain,argp->map);
+
+       if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
+               goto bail;
+       YPLOG( "first_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->domain, argp->map);
+       
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.stat = YP_YPERR;
+       } else {
+               res = ypdb_get_first(argp->domain,argp->map,FALSE);
+       }
+
+#ifdef DEBUG
+       yplog("  first2_status: %s", yperr_string(ypprot_err(res.stat)));
+#endif
+
+       return (&res);
+}
+
+ypresp_key_val *
+ypproc_next_2_svc(argp, rqstp)
+       ypreq_key *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_key_val res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure = ypdb_secure(argp->domain,argp->map);
+
+       if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
+               goto bail;
+       YPLOG(
+         "next_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.stat = YP_YPERR;
+       } else {
+               res = ypdb_get_next(argp->domain,argp->map,argp->key,FALSE);
+       }
+
+#ifdef DEBUG
+       yplog("  next2_status: %s", yperr_string(ypprot_err(res.stat)));
+#endif
+
+       return (&res);
+}
+
+ypresp_xfr *
+ypproc_xfr_2_svc(argp, rqstp)
+       ypreq_xfr *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_xfr res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       pid_t   pid;
+       char    tid[11];
+       char    prog[11];
+       char    port[11];
+       char    ypxfr_proc[] = YPXFR_PROC;
+       char    *ipadd;
+
+       bzero((char *)&res, sizeof(res));
+
+       YPLOG("xfr_2: caller=[%s].%d, auth_ok=%s, domain=%s, tid=%d, prog=%d",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), 
+         argp->map_parms.domain, argp->transid, argp->prog);
+       YPLOG("       ipadd=%s, port=%d, map=%s", inet_ntoa(caller->sin_addr),
+         argp->port, argp->map_parms.map);
+
+       if (strchr(argp->map_parms.domain, '/') ||
+           strchr(argp->map_parms.map, '/') ||
+           ntohs(caller->sin_port) >= IPPORT_RESERVED) {
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       snprintf(tid, sizeof(tid), "%d",argp->transid);
+       snprintf(prog, sizeof(prog), "%d", argp->prog);
+       snprintf(port, sizeof(port), "%d", argp->port);
+       ipadd = inet_ntoa(caller->sin_addr);
+
+       pid = vfork();
+       if (pid == -1) {
+               svcerr_systemerr(rqstp->rq_xprt);
+               return(NULL);
+       }
+       if (pid == 0) {
+               execl(ypxfr_proc, "ypxfr", "-d", argp->map_parms.domain,
+                   "-C",tid, prog, ipadd, port, argp->map_parms.map, NULL);
+               _exit(1);
+       }
+       
+       /*
+        * XXX: fill in res
+        */
+       return (&res);
+}
+
+void *
+ypproc_clear_2_svc(argp, rqstp)
+       void *argp;
+        struct svc_req *rqstp;
+{
+       static char *res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+
+       YPLOG( "clear_2: caller=[%s].%d, auth_ok=%s, opt=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
+#ifdef OPTDB
+               True
+#else
+               False
+#endif
+       );
+
+       if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
+               ok = FALSE;
+
+       if (!ok) {
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       res = NULL;
+       
+#ifdef OPTDB
+        ypdb_close_all();
+#endif
+
+       return ((void *)&res);
+}
+
+ypresp_all *
+ypproc_all_2_svc(argp, rqstp)
+       ypreq_nokey *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_all res;
+       pid_t pid;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure = ypdb_secure(argp->domain,argp->map);
+
+       if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
+               goto bail;
+       YPLOG( "all_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure), argp->domain, argp->map);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       bzero((char *)&res, sizeof(res));
+       
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.ypresp_all_u.val.stat = YP_YPERR;
+               return(&res);
+       }
+
+       pid = fork();
+
+       if (pid) {
+
+               if (pid == -1) {
+                       /* XXXCDC An error has occurred */
+               }
+               
+               return(NULL); /* PARENT: continue */
+               
+       }
+       /* CHILD: send result, then exit */
+
+       if (!svc_sendreply(rqstp->rq_xprt, ypdb_xdr_get_all, (char *) argp)) {
+               svcerr_systemerr(rqstp->rq_xprt);
+       }
+
+       /* note: no need to free args, we are exiting */
+
+       exit(0);
+}
+
+ypresp_master *
+ypproc_master_2_svc(argp, rqstp)
+       ypreq_nokey *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_master res;
+       static peername nopeer = "";
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure = ypdb_secure(argp->domain,argp->map);
+
+       if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
+               goto bail;
+       YPLOG( "master_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure), argp->domain, argp->map);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.stat = YP_YPERR;
+       } else {
+               res = ypdb_get_master(argp->domain,argp->map);
+       }
+
+#ifdef DEBUG
+       yplog("  master2_status: %s", yperr_string(ypprot_err(res.stat)));
+#endif
+
+       /* This code was added because a yppoll <unknown-domain> */
+       /* from a sun crashed the server in xdr_string, trying   */
+       /* to access the peer through a NULL-pointer. yppoll in  */
+       /* this server start asking for order. If order is ok    */
+       /* then it will ask for master. SunOS 4 asks for both    */
+       /* always. I'm not sure this is the best place for the   */
+       /* fix, but for now it will do. xdr_peername or          */
+       /* xdr_string in ypserv_xdr.c may be a better place?     */
+       
+       if (res.peer == NULL) {
+               res.peer = nopeer;
+       }
+
+       /* End of fix                                            */
+
+       return (&res);
+}
+
+
+ypresp_order *
+ypproc_order_2_svc(argp, rqstp)
+       ypreq_nokey *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_order res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure = ypdb_secure(argp->domain,argp->map);
+
+       if (strchr(argp->domain, '/'))
+               goto bail;
+       YPLOG( "order_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure), argp->domain, argp->map);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.stat = YP_YPERR;
+       } else if (strchr(argp->map, '/')) {
+               res.stat = YP_NOMAP;
+       } else {
+               res = ypdb_get_order(argp->domain,argp->map);
+       }
+
+#ifdef DEBUG
+       yplog("  order2_status: %s", yperr_string(ypprot_err(res.stat)));
+#endif
+
+       return (&res);
+}
+
+
+ypresp_maplist *
+ypproc_maplist_2_svc(argp, rqstp)
+       domainname *argp;
+        struct svc_req *rqstp;
+{
+       static ypresp_maplist res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       static char domain_path[MAXPATHLEN];
+       struct stat finfo;
+       DIR   *dirp = NULL;
+       struct dirent *dp;
+       char  *suffix;
+       ypstat status;
+       struct ypmaplist *m;
+       char  *map_name;
+
+       if (strchr(*argp, '/'))
+               goto bail;
+       YPLOG("maplist_2: caller=[%s].%d, auth_ok=%s, domain=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
+         *argp);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       bzero((char *)&res, sizeof(res));
+       
+       snprintf(domain_path,MAXPATHLEN, "%s/%s",YP_DB_PATH,*argp);
+
+       status = YP_TRUE;
+
+       res.maps = NULL;
+
+       if (!((stat(domain_path, &finfo) == 0) &&
+               ((finfo.st_mode & S_IFMT) == S_IFDIR))) 
+               status = YP_NODOM;
+
+       if (status >= 0) {
+         if ((dirp = opendir(domain_path)) == NULL) {
+           status = YP_NODOM;
+         }
+       }
+
+       if (status >= 0) {
+         for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+           if ((!strcmp(dp->d_name, ".")) ||
+               ((!strcmp(dp->d_name, ".."))) ||
+               (dp->d_namlen < 4))
+             continue;
+           suffix = (char *) &dp->d_name[dp->d_namlen-3];
+           if (strcmp(suffix,".db") == 0) {
+
+             if ((m = (struct ypmaplist *)
+                  malloc((unsigned) sizeof(struct ypmaplist))) == NULL) {
+               status = YP_YPERR;
+               break;
+             }
+
+             if ((map_name = (char *)
+                  malloc((unsigned) dp->d_namlen - 2)) == NULL) {
+               status = YP_YPERR;
+               break;
+             }
+
+             m->next = res.maps;
+             m->map = map_name;
+             res.maps = m;
+             strncpy(map_name, dp->d_name, dp->d_namlen - 3);
+             m->map[dp->d_namlen - 3] = '\0';
+             
+           }
+         }
+       }
+       
+       if (dirp != NULL) {
+         closedir(dirp);
+       }
+
+       res.stat = status;
+       
+#ifdef DEBUG
+       yplog("  maplist_status: %s", yperr_string(ypprot_err(res.stat)));
+#endif
+
+       return (&res);
+}
+
+void *
+ypproc_null_1_svc(argp, rqstp)
+       void *argp;
+        struct svc_req *rqstp;
+{
+       static char *result;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+
+       YPLOG("null_1: caller=[%s].%d, auth_ok=%s",
+             inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok));
+
+       if (!ok) {
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       result = NULL;
+
+       return ((void *)&result);
+}
+
+bool_t *
+ypproc_domain_1_svc(argp, rqstp)
+       domainname *argp;
+        struct svc_req *rqstp;
+{
+       static bool_t result; /* is domain_served? */
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       static char domain_path[MAXPATHLEN];
+       struct stat finfo;
+
+       if (strchr(*argp, '/'))
+               goto bail;
+       snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
+       result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
+                                   (finfo.st_mode & S_IFDIR));
+
+       YPLOG("domain_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
+             inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), 
+             TORF(ok), *argp, TORF(result));
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       return (&result);
+}
+
+bool_t *
+ypproc_domain_nonack_1_svc(argp, rqstp)
+       domainname *argp;
+        struct svc_req *rqstp;
+{
+       static bool_t result; /* is domain served? */
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       static char domain_path[MAXPATHLEN];
+       struct stat finfo;
+
+       if (strchr(*argp, '/'))
+               goto bail;
+       snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
+       result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
+                                   (finfo.st_mode & S_IFDIR));
+
+       YPLOG(
+         "domain_nonack_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), 
+         *argp, TORF(result));
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (!result) {
+               return(NULL); /* don't send nack */
+       }
+
+       return (&result);
+}
+
+ypresponse *
+ypproc_match_1_svc(argp, rqstp)
+       yprequest *argp;
+        struct svc_req *rqstp;
+{
+       static ypresponse res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure;
+
+       if (strchr(argp->ypmatch_req_domain, '/') ||
+           strchr(argp->ypmatch_req_map, '/'))
+               goto bail;
+       res.yp_resptype = YPMATCH_RESPTYPE;
+       res.ypmatch_resp_valptr = "";
+       res.ypmatch_resp_valsize = 0;
+
+       if (argp->yp_reqtype != YPMATCH_REQTYPE) {
+               res.ypmatch_resp_status = YP_BADARGS;
+               return(&res);
+       }
+
+       secure = ypdb_secure(argp->ypmatch_req_domain, argp->ypmatch_req_map);
+
+       YPLOG(
+         "match_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->ypmatch_req_domain,  argp->ypmatch_req_map,
+         argp->ypmatch_req_keysize, argp->ypmatch_req_keyptr);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.ypmatch_resp_status = YP_YPERR;
+       } else {
+               res.ypmatch_resp_val =
+                     ypdb_get_record(argp->ypmatch_req_domain,
+                                     argp->ypmatch_req_map,
+                                     argp->ypmatch_req_keydat,
+                                     FALSE);
+       }
+
+#ifdef DEBUG
+       yplog("  match1_status: %s",
+             yperr_string(ypprot_err(res.ypmatch_resp_status)));
+#endif
+
+       return (&res);
+}
+
+ypresponse *
+ypproc_first_1_svc(argp, rqstp)
+       yprequest *argp;
+        struct svc_req *rqstp;
+{
+       static ypresponse res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure;
+
+       if (strchr(argp->ypfirst_req_domain, '/') ||
+           strchr(argp->ypfirst_req_map, '/'))
+               goto bail;
+       res.yp_resptype = YPFIRST_RESPTYPE;
+       res.ypfirst_resp_valptr  = res.ypfirst_resp_keyptr  = "";
+       res.ypfirst_resp_valsize = res.ypfirst_resp_keysize = 0;
+
+       if (argp->yp_reqtype != YPREQ_NOKEY) {
+               res.ypfirst_resp_status = YP_BADARGS;
+               return(&res);
+       }
+
+       secure = ypdb_secure(argp->ypfirst_req_domain, argp->ypfirst_req_map);
+
+       YPLOG( "first_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->ypfirst_req_domain, argp->ypfirst_req_map);
+       
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.ypfirst_resp_status = YP_YPERR;
+       } else {
+               res.ypfirst_resp_val =
+                     ypdb_get_first(argp->ypfirst_req_domain,
+                                    argp->ypfirst_req_map,
+                                    FALSE);
+       }
+
+#ifdef DEBUG
+       yplog("  first1_status: %s",
+             yperr_string(ypprot_err(res.ypfirst_resp_status)));
+#endif
+
+       return (&res);
+}
+
+ypresponse *
+ypproc_next_1_svc(argp, rqstp)
+       yprequest *argp;
+        struct svc_req *rqstp;
+{
+       static ypresponse res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure;
+
+       if (strchr(argp->ypnext_req_domain, '/') ||
+           strchr(argp->ypnext_req_map, '/'))
+               goto bail;
+       res.yp_resptype = YPNEXT_RESPTYPE;
+       res.ypnext_resp_valptr  = res.ypnext_resp_keyptr  = "";
+       res.ypnext_resp_valsize = res.ypnext_resp_keysize = 0;
+
+       if (argp->yp_reqtype != YPNEXT_REQTYPE) {
+               res.ypnext_resp_status = YP_BADARGS;
+               return(&res);
+       }
+
+       secure = ypdb_secure(argp->ypnext_req_domain, argp->ypnext_req_map);
+
+       YPLOG(
+         "next_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->ypnext_req_domain,  argp->ypnext_req_map,
+         argp->ypnext_req_keysize, argp->ypnext_req_keyptr);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+               res.ypnext_resp_status = YP_YPERR;
+       } else {
+               res.ypnext_resp_val =
+                     ypdb_get_next(argp->ypnext_req_domain,
+                                   argp->ypnext_req_map,
+                                   argp->ypnext_req_keydat,
+                                   FALSE);
+       }
+
+#ifdef DEBUG
+       yplog("  next1_status: %s",
+             yperr_string(ypprot_err(res.ypnext_resp_status)));
+#endif
+
+       return (&res);
+}
+
+ypresponse *
+ypproc_poll_1_svc(argp, rqstp)
+       yprequest *argp;
+        struct svc_req *rqstp;
+{
+       static ypresponse res;
+       ypresp_order order;
+       ypresp_master master;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure;
+
+       if (strchr(argp->yppoll_req_domain, '/') ||
+           strchr(argp->yppoll_req_map, '/'))
+               goto bail;
+       res.yp_resptype = YPPOLL_RESPTYPE;
+       res.yppoll_resp_domain = argp->yppoll_req_domain;
+       res.yppoll_resp_map = argp->yppoll_req_map;
+       res.yppoll_resp_ordernum = 0;
+       res.yppoll_resp_owner = "";
+
+       if (argp->yp_reqtype != YPPOLL_REQTYPE) {
+               return(&res);
+       }
+
+       secure = ypdb_secure(argp->yppoll_req_domain, argp->yppoll_req_map);
+
+       YPLOG( "poll_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->yppoll_req_domain, argp->yppoll_req_map);
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       if (!(secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED))) {
+               order = ypdb_get_order(argp->yppoll_req_domain,
+                                      argp->yppoll_req_map);
+               master = ypdb_get_master(argp->yppoll_req_domain,
+                                        argp->yppoll_req_map);
+               res.yppoll_resp_ordernum = order.ordernum;
+               res.yppoll_resp_owner = master.peer;
+       }
+
+#ifdef DEBUG
+       yplog("  poll1_status: %s", "none");
+#endif
+       return (&res);
+}
+
+void *
+ypproc_push_1_svc(argp, rqstp)
+       yprequest *argp;
+        struct svc_req *rqstp;
+{
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure;
+       pid_t   pid;
+       char    yppush_proc[] = YPPUSH_PROC;
+
+       if (strchr(argp->yppush_req_domain, '/') ||
+           strchr(argp->yppush_req_map, '/'))
+               goto bail;
+       if (argp->yp_reqtype != YPPUSH_REQTYPE) {
+               return(NULL);
+       }
+
+       secure = ypdb_secure(argp->yppush_req_domain, argp->yppush_req_map);
+
+       YPLOG( "push_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->yppush_req_domain, argp->yppush_req_map);
+
+       if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
+               ok = FALSE;
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       pid = vfork();
+       if (pid == -1) {
+               svcerr_systemerr(rqstp->rq_xprt);
+               return(NULL);
+       }
+       if (pid == 0) {
+               execl(yppush_proc, "yppush", "-d", argp->yppush_req_domain,
+                     argp->yppush_req_map, NULL);
+               _exit(1);
+       }
+       
+       return (NULL);
+}
+
+void *
+ypproc_pull_1_svc(argp, rqstp)
+       yprequest *argp;
+        struct svc_req *rqstp;
+{
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure;
+       pid_t   pid;
+       char    ypxfr_proc[] = YPXFR_PROC;
+
+       if (strchr(argp->yppull_req_domain, '/') ||
+           strchr(argp->yppull_req_map, '/'))
+               goto bail;
+       if (argp->yp_reqtype != YPPULL_REQTYPE) {
+               return(NULL);
+       }
+
+       secure = ypdb_secure(argp->yppull_req_domain, argp->yppull_req_map);
+
+       YPLOG( "pull_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->yppull_req_domain, argp->yppull_req_map);
+
+       if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
+               ok = FALSE;
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       pid = vfork();
+       if (pid == -1) {
+               svcerr_systemerr(rqstp->rq_xprt);
+               return(NULL);
+       }
+       if (pid == 0) {
+               execl(ypxfr_proc, "ypxfr", "-d", argp->yppull_req_domain,
+                     argp->yppull_req_map, NULL);
+               _exit(1);
+       }
+       
+       return (NULL);
+}
+
+void *
+ypproc_get_1_svc(argp, rqstp)
+       yprequest *argp;
+        struct svc_req *rqstp;
+{
+       char *res;
+       struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
+       int ok = acl_check_host(&caller->sin_addr);
+       int secure;
+       pid_t   pid;
+       char    ypxfr_proc[] = YPXFR_PROC;
+
+       if (strchr(argp->ypget_req_domain, '/') ||
+           strchr(argp->ypget_req_map, '/'))
+               goto bail;
+       if (argp->yp_reqtype != YPGET_REQTYPE) {
+               return(NULL);
+       }
+
+       secure = ypdb_secure(argp->ypget_req_domain, argp->ypget_req_map);
+
+       YPLOG( "get_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, owner=%s",
+         inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
+         TORF(ok), TORF(secure),
+         argp->ypget_req_domain, argp->ypget_req_map,
+         argp->ypget_req_owner);
+
+       if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
+               ok = FALSE;
+
+       if (!ok) {
+bail:
+               svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
+               return(NULL);
+       }
+
+       pid = vfork();
+       if (pid == -1) {
+               svcerr_systemerr(rqstp->rq_xprt);
+               return(NULL);
+       }
+       if (pid == 0) {
+               execl(ypxfr_proc, "ypxfr", "-d", argp->ypget_req_domain, "-h",
+                     argp->ypget_req_owner, argp->yppush_req_map, NULL);
+               _exit(1);
+       }
+       
+       return (NULL);
+}
diff --git a/ypserv.tproj/ypserv_xdr.c b/ypserv.tproj/ypserv_xdr.c
new file mode 100644 (file)
index 0000000..2e1fb2a
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "yp.h"
+#ifndef lint
+static char rcsid[] = "$OpenBSD: ypserv_xdr.c,v 1.3 1996/05/30 09:53:31 deraadt Exp $";
+#endif /* not lint */
+
+__private_extern__
+bool_t
+xdr_ypstat(xdrs, objp)
+       XDR *xdrs;
+       ypstat *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypxfrstat(xdrs, objp)
+       XDR *xdrs;
+       ypxfrstat *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_domainname(xdrs, objp)
+       XDR *xdrs;
+       domainname *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_mapname(xdrs, objp)
+       XDR *xdrs;
+       mapname *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_string(xdrs, objp, YPMAXMAP)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_peername(xdrs, objp)
+       XDR *xdrs;
+       peername *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_string(xdrs, objp, YPMAXPEER)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_keydat(xdrs, objp)
+       XDR *xdrs;
+       keydat *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_bytes(xdrs, (char **)&objp->keydat_val, (u_int *)&objp->keydat_len, YPMAXRECORD)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_valdat(xdrs, objp)
+       XDR *xdrs;
+       valdat *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_bytes(xdrs, (char **)&objp->valdat_val, (u_int *)&objp->valdat_len, YPMAXRECORD)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypmap_parms(xdrs, objp)
+       XDR *xdrs;
+       ypmap_parms *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_domainname(xdrs, &objp->domain)) {
+                return (FALSE);
+        }
+        if (!xdr_mapname(xdrs, &objp->map)) {
+                return (FALSE);
+        }
+        if (!xdr_u_int(xdrs, &objp->ordernum)) {
+                return (FALSE);
+        }
+        if (!xdr_peername(xdrs, &objp->peer)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypreq_key(xdrs, objp)
+       XDR *xdrs;
+       ypreq_key *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_domainname(xdrs, &objp->domain)) {
+                return (FALSE);
+        }
+        if (!xdr_mapname(xdrs, &objp->map)) {
+                return (FALSE);
+        }
+        if (!xdr_keydat(xdrs, &objp->key)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypreq_nokey(xdrs, objp)
+       XDR *xdrs;
+       ypreq_nokey *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_domainname(xdrs, &objp->domain)) {
+                return (FALSE);
+        }
+        if (!xdr_mapname(xdrs, &objp->map)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypreq_xfr(xdrs, objp)
+       XDR *xdrs;
+       ypreq_xfr *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_ypmap_parms(xdrs, &objp->map_parms)) {
+                return (FALSE);
+        }
+        if (!xdr_u_int(xdrs, &objp->transid)) {
+                return (FALSE);
+        }
+        if (!xdr_u_int(xdrs, &objp->prog)) {
+                return (FALSE);
+        }
+        if (!xdr_u_int(xdrs, &objp->port)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypresp_val(xdrs, objp)
+       XDR *xdrs;
+       ypresp_val *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_ypstat(xdrs, &objp->stat)) {
+                return (FALSE);
+        }
+        if (!xdr_valdat(xdrs, &objp->val)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypresp_key_val(xdrs, objp)
+       XDR *xdrs;
+       ypresp_key_val *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_ypstat(xdrs, &objp->stat)) {
+                return (FALSE);
+        }
+        if (!xdr_valdat(xdrs, &objp->val)) {
+                return (FALSE);
+        }
+        if (!xdr_keydat(xdrs, &objp->key)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypresp_master(xdrs, objp)
+       XDR *xdrs;
+       ypresp_master *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_ypstat(xdrs, &objp->stat)) {
+                return (FALSE);
+        }
+        if (!xdr_peername(xdrs, &objp->peer)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypresp_order(xdrs, objp)
+       XDR *xdrs;
+       ypresp_order *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_ypstat(xdrs, &objp->stat)) {
+                return (FALSE);
+        }
+        if (!xdr_u_int(xdrs, &objp->ordernum)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypresp_all(xdrs, objp)
+       XDR *xdrs;
+       ypresp_all *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_bool(xdrs, &objp->more)) {
+                return (FALSE);
+        }
+       switch (objp->more) {
+       case TRUE:
+                if (!xdr_ypresp_key_val(xdrs, &objp->ypresp_all_u.val)) {
+                        return (FALSE);
+                }
+               break;
+       case FALSE:
+               break;
+       default:
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypresp_xfr(xdrs, objp)
+       XDR *xdrs;
+       ypresp_xfr *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_u_int(xdrs, &objp->transid)) {
+                return (FALSE);
+        }
+        if (!xdr_ypxfrstat(xdrs, &objp->xfrstat)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypmaplist(xdrs, objp)
+       XDR *xdrs;
+       ypmaplist *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_mapname(xdrs, &objp->map)) {
+                return (FALSE);
+        }
+        if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(ypmaplist), (xdrproc_t)xdr_ypmaplist)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypresp_maplist(xdrs, objp)
+       XDR *xdrs;
+       ypresp_maplist *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_ypstat(xdrs, &objp->stat)) {
+                return (FALSE);
+        }
+        if (!xdr_pointer(xdrs, (char **)&objp->maps, sizeof(ypmaplist), (xdrproc_t)xdr_ypmaplist)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_yppush_status(xdrs, objp)
+       XDR *xdrs;
+       yppush_status *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_yppushresp_xfr(xdrs, objp)
+       XDR *xdrs;
+       yppushresp_xfr *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_u_int(xdrs, &objp->transid)) {
+                return (FALSE);
+        }
+        if (!xdr_yppush_status(xdrs, &objp->status)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypbind_resptype(xdrs, objp)
+       XDR *xdrs;
+       ypbind_resptype *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypbind_binding(xdrs, objp)
+       XDR *xdrs;
+       ypbind_binding *objp;
+{
+
+        register long *buf;
+
+        int i;
+        if (!xdr_opaque(xdrs, objp->ypbind_binding_addr, 4)) {
+                return (FALSE);
+        }
+        if (!xdr_opaque(xdrs, objp->ypbind_binding_port, 2)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+__private_extern__
+bool_t
+xdr_ypbind_resp(xdrs, objp)
+       XDR *xdrs;
+       ypbind_resp *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_ypbind_resptype(xdrs, &objp->ypbind_status)) {
+                return (FALSE);
+        }
+       switch (objp->ypbind_status) {
+       case YPBIND_FAIL_VAL:
+                if (!xdr_u_int(xdrs, &objp->ypbind_resp_u.ypbind_error)) {
+                        return (FALSE);
+                }
+               break;
+       case YPBIND_SUCC_VAL:
+                if (!xdr_ypbind_binding(xdrs, &objp->ypbind_resp_u.ypbind_bindinfo)) {
+                        return (FALSE);
+                }
+               break;
+       default:
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypbind_setdom(xdrs, objp)
+       XDR *xdrs;
+       ypbind_setdom *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_domainname(xdrs, &objp->ypsetdom_domain)) {
+                return (FALSE);
+        }
+        if (!xdr_ypbind_binding(xdrs, &objp->ypsetdom_binding)) {
+                return (FALSE);
+        }
+        if (!xdr_u_int(xdrs, &objp->ypsetdom_vers)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
diff --git a/ypserv.tproj/ypserv_xdr_v1.c b/ypserv.tproj/ypserv_xdr_v1.c
new file mode 100644 (file)
index 0000000..3870f58
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "yp.h"
+#include "ypv1.h"
+#ifndef lint
+static char rcsid[] = "$OpenBSD: ypserv_xdr_v1.c,v 1.1 1997/03/30 20:51:22 maja Exp $";
+#endif /* not lint */
+
+bool_t
+xdr_ypreqtype(xdrs, objp)
+       XDR *xdrs;
+       ypreqtype *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypresptype(xdrs, objp)
+       XDR *xdrs;
+       ypresptype *objp;
+{
+
+        register long *buf;
+
+        if (!xdr_enum(xdrs, (enum_t *)objp)) {
+                return (FALSE);
+        }
+       return (TRUE);
+}
+
+bool_t
+xdr_yprequest(xdrs, objp)
+       XDR *xdrs;
+       yprequest *objp;
+{
+       if (!xdr_ypreqtype(xdrs, &objp->yp_reqtype)) {
+               printf("error 1\n");
+               return (FALSE);
+       }
+       switch (objp->yp_reqtype) {
+       case YPREQ_KEY:
+               if (!xdr_ypreq_key(xdrs, &objp->yp_reqbody.yp_req_keytype)) {
+                       printf("error 2\n");
+                       return (FALSE);
+               }
+               break;
+       case YPREQ_NOKEY:
+               if (!xdr_ypreq_nokey(xdrs, &objp->yp_reqbody.yp_req_nokeytype)) {
+                       printf("error 3\n");
+                       return (FALSE);
+               }
+               break;
+       case YPREQ_MAP_PARMS:
+               if (!xdr_ypmap_parms(xdrs, &objp->yp_reqbody.yp_req_map_parmstype)) {
+                       printf("error 4\n");
+                       return (FALSE);
+               }
+               break;
+       default:
+               printf("error 5\n");
+               return (FALSE);         
+       }
+       return (TRUE);
+}
+
+bool_t
+xdr_ypresponse(xdrs, objp)
+       XDR *xdrs;
+       ypresponse *objp;
+{
+
+       register long *buf;
+
+       if (!xdr_ypresptype(xdrs, &objp->yp_resptype)) {
+               return (FALSE);
+       }
+       switch (objp->yp_resptype) {
+       case YPRESP_VAL:
+               if (!xdr_ypresp_val(xdrs, &objp->yp_respbody.yp_resp_valtype)) {
+                       return (FALSE);
+               }
+               break;
+       case YPRESP_KEY_VAL:
+               if (!xdr_ypresp_key_val(xdrs, &objp->yp_respbody.yp_resp_key_valtype)) {
+                       return (FALSE);
+               }
+               break;
+       case YPRESP_MAP_PARMS:
+               if (!xdr_ypmap_parms(xdrs, &objp->yp_respbody.yp_resp_map_parmstype)) {
+                       return (FALSE);
+               }
+               break;
+       default:
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
diff --git a/ypserv.tproj/ypv1.h b/ypserv.tproj/ypv1.h
new file mode 100644 (file)
index 0000000..d378f83
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $OpenBSD: ypv1.h,v 1.2 1997/07/25 20:12:31 mickey Exp $ */
+
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _YPV1_H_RPCGEN
+#define _YPV1_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+#define YPOLDVERS ((u_long)1)
+
+enum ypreqtype {
+       YPREQ_KEY = 1,
+       YPREQ_NOKEY = 2,
+       YPREQ_MAP_PARMS = 3
+};
+typedef enum ypreqtype ypreqtype;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypreqtype(XDR *, ypreqtype*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypreqtype(XDR *, ypreqtype*);
+#else /* Old Style C */ 
+bool_t xdr_ypreqtype();
+#endif /* Old Style C */ 
+
+typedef struct {
+       ypreqtype yp_reqtype;
+       union {
+               struct ypreq_key yp_req_keytype;
+               struct ypreq_nokey yp_req_nokeytype;
+               struct ypmap_parms yp_req_map_parmstype;
+       }yp_reqbody;
+} yprequest;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_yprequest(XDR *, yprequest*);
+#elif defined(__STDC__)
+extern  bool_t xdr_yprequest(XDR *, yprequest*);
+#else /* Old Style C */ 
+bool_t xdr_yprequest();
+#endif /* Old Style C */ 
+
+#define YPMATCH_REQTYPE YPREQ_KEY
+#define ypmatch_req_domain yp_reqbody.yp_req_keytype.domain
+#define ypmatch_req_map yp_reqbody.yp_req_keytype.map
+#define ypmatch_req_keydat yp_reqbody.yp_req_keytype.key
+#define ypmatch_req_keyptr yp_reqbody.yp_req_keytype.key.keydat_val
+#define ypmatch_req_keysize yp_reqbody.yp_req_keytype.key.keydat_len
+
+#define YPFIRST_REQTYPE YPREQ_NOKEY
+#define ypfirst_req_domain yp_reqbody.yp_req_nokeytype.domain
+#define ypfirst_req_map yp_reqbody.yp_req_nokeytype.map
+
+#define YPNEXT_REQTYPE YPREQ_KEY
+#define ypnext_req_domain yp_reqbody.yp_req_keytype.domain
+#define ypnext_req_map yp_reqbody.yp_req_keytype.map
+#define ypnext_req_keydat yp_reqbody.yp_req_keytype.key
+#define ypnext_req_keyptr yp_reqbody.yp_req_keytype.key.keydat_val
+#define ypnext_req_keysize yp_reqbody.yp_req_keytype.key.keydat_len
+
+#define YPPUSH_REQTYPE YPREQ_NOKEY
+#define yppush_req_domain yp_reqbody.yp_req_nokeytype.domain
+#define yppush_req_map yp_reqbody.yp_req_nokeytype.map
+
+#define YPPULL_REQTYPE YPREQ_NOKEY
+#define yppull_req_domain yp_reqbody.yp_req_nokeytype.domain
+#define yppull_req_map yp_reqbody.yp_req_nokeytype.map
+
+#define YPPOLL_REQTYPE YPREQ_NOKEY
+#define yppoll_req_domain yp_reqbody.yp_req_nokeytype.domain
+#define yppoll_req_map yp_reqbody.yp_req_nokeytype.map
+
+#define YPGET_REQTYPE YPREQ_MAP_PARMS
+#define ypget_req_domain yp_reqbody.yp_req_map_parmstype.domain
+#define ypget_req_map yp_reqbody.yp_req_map_parmstype.map
+#define ypget_req_ordernum yp_reqbody.yp_req_map_parmstype.ordernum
+#define ypget_req_owner yp_reqbody.yp_req_map_parmstype.peer
+
+enum ypresptype {
+       YPRESP_VAL = 1,
+       YPRESP_KEY_VAL = 2,
+       YPRESP_MAP_PARMS = 3
+};
+typedef enum ypresptype ypresptype;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresptype(XDR *, ypresptype*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresptype(XDR *, ypresptype*);
+#else /* Old Style C */ 
+bool_t xdr_ypresptype();
+#endif /* Old Style C */ 
+
+typedef struct {
+       ypresptype yp_resptype;
+       union {
+               struct ypresp_val yp_resp_valtype;
+               struct ypresp_key_val yp_resp_key_valtype;
+               struct ypmap_parms yp_resp_map_parmstype;
+       } yp_respbody;
+} ypresponse;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ypresponse(XDR *, ypresponse*);
+#elif defined(__STDC__)
+extern  bool_t xdr_ypresponse(XDR *, ypresponse*);
+#else /* Old Style C */ 
+bool_t xdr_ypresponse();
+#endif /* Old Style C */ 
+
+#define YPMATCH_RESPTYPE YPRESP_VAL
+#define ypmatch_resp_status yp_respbody.yp_resp_valtype.stat
+#define ypmatch_resp_val yp_respbody.yp_resp_valtype
+#define ypmatch_resp_valdat yp_respbody.yp_resp_valtype.val
+#define ypmatch_resp_valptr yp_respbody.yp_resp_valtype.val.valdat_val
+#define ypmatch_resp_valsize yp_respbody.yp_resp_valtype.val.valdat_len
+
+#define YPFIRST_RESPTYPE YPRESP_KEY_VAL
+#define ypfirst_resp_status yp_respbody.yp_resp_key_valtype.stat
+#define ypfirst_resp_keydat yp_respbody.yp_resp_key_valtype.key
+#define ypfirst_resp_keyptr yp_respbody.yp_resp_key_valtype.key.keydat_val
+#define ypfirst_resp_keysize yp_respbody.yp_resp_key_valtype.key.keydat_len
+#define ypfirst_resp_val yp_respbody.yp_resp_key_valtype
+#define ypfirst_resp_valdat yp_respbody.yp_resp_key_valtype.val
+#define ypfirst_resp_valptr yp_respbody.yp_resp_key_valtype.val.valdat_val
+#define ypfirst_resp_valsize yp_respbody.yp_resp_key_valtype.val.valdat_len
+
+#define YPNEXT_RESPTYPE YPRESP_KEY_VAL
+#define ypnext_resp_status yp_respbody.yp_resp_key_valtype.stat
+#define ypnext_resp_keydat yp_respbody.yp_resp_key_valtype.key
+#define ypnext_resp_keyptr yp_respbody.yp_resp_key_valtype.key.keydat_val
+#define ypnext_resp_keysize yp_respbody.yp_resp_key_valtype.key.keydat_len
+#define ypnext_resp_val yp_respbody.yp_resp_key_valtype
+#define ypnext_resp_valdat yp_respbody.yp_resp_key_valtype.val
+#define ypnext_resp_valptr yp_respbody.yp_resp_key_valtype.val.valdat_val
+#define ypnext_resp_valsize yp_respbody.yp_resp_key_valtype.val.valdat_len
+
+#define YPPOLL_RESPTYPE YPRESP_MAP_PARMS
+#define yppoll_resp_domain yp_respbody.yp_resp_map_parmstype.domain
+#define yppoll_resp_map yp_respbody.yp_resp_map_parmstype.map
+#define yppoll_resp_ordernum yp_respbody.yp_resp_map_parmstype.ordernum
+#define yppoll_resp_owner yp_respbody.yp_resp_map_parmstype.peer
+
+#ifdef __cplusplus
+#define YPOLDPROC_NULL ((u_long)0)
+extern "C" void * ypproc_null_1(void *, CLIENT *);
+extern "C" void * ypproc_null_1_svc(void *, struct svc_req *);
+#define YPOLDPROC_DOMAIN ((u_long)1)
+extern "C" bool_t * ypproc_domain_1(domainname *, CLIENT *);
+extern "C" bool_t * ypproc_domain_1_svc(domainname *, struct svc_req *);
+#define YPOLDPROC_DOMAIN_NONACK ((u_long)2)
+extern "C" bool_t * ypproc_domain_nonack_1(domainname *, CLIENT *);
+extern "C" bool_t * ypproc_domain_nonack_1_svc(domainname *, struct svc_req *);
+#define YPOLDPROC_MATCH ((u_long)3)
+extern "C" ypresponse * ypproc_match_1(yprequest *, CLIENT *);
+extern "C" ypresponse * ypproc_match_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_FIRST ((u_long)4)
+extern "C" ypresponse * ypproc_first_1(yprequest *, CLIENT *);
+extern "C" ypresponse * ypproc_first_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_NEXT ((u_long)5)
+extern "C" ypresponse * ypproc_next_1(yprequest *, CLIENT *);
+extern "C" ypresponse * ypproc_next_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_POLL ((u_long)6)
+extern "C" ypresponse * ypproc_poll_1(yprequest *, CLIENT *);
+extern "C" ypresponse * ypproc_poll_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_PUSH ((u_long)7)
+extern "C" void * ypproc_push_1(yprequest *, CLIENT *);
+extern "C" void * ypproc_push_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_PULL ((u_long)8)
+extern "C" void * ypproc_pull_1(yprequest *, CLIENT *);
+extern "C" void * ypproc_pull_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_GET ((u_long)9)
+extern "C" void * ypproc_get_1(yprequest *, CLIENT *);
+extern "C" void * ypproc_get_1_svc(yprequest *, struct svc_req *);
+
+#elif defined(__STDC__)
+#define YPOLDPROC_NULL ((u_long)0)
+extern  void * ypproc_null_1(void *, CLIENT *);
+extern  void * ypproc_null_1_svc(void *, struct svc_req *);
+#define YPOLDPROC_DOMAIN ((u_long)1)
+extern  bool_t * ypproc_domain_1(domainname *, CLIENT *);
+extern  bool_t * ypproc_domain_1_svc(domainname *, struct svc_req *);
+#define YPOLDPROC_DOMAIN_NONACK ((u_long)2)
+extern  bool_t * ypproc_domain_nonack_1(domainname *, CLIENT *);
+extern  bool_t * ypproc_domain_nonack_1_svc(domainname *, struct svc_req *);
+#define YPOLDPROC_MATCH ((u_long)3)
+extern  ypresponse * ypproc_match_1(yprequest *, CLIENT *);
+extern  ypresponse * ypproc_match_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_FIRST ((u_long)4)
+extern  ypresponse * ypproc_first_1(yprequest *, CLIENT *);
+extern  ypresponse * ypproc_first_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_NEXT ((u_long)5)
+extern  ypresponse * ypproc_next_1(yprequest *, CLIENT *);
+extern  ypresponse * ypproc_next_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_POLL ((u_long)6)
+extern  ypresponse * ypproc_poll_1(yprequest *, CLIENT *);
+extern  ypresponse * ypproc_poll_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_PUSH ((u_long)7)
+extern  void * ypproc_push_1(yprequest *, CLIENT *);
+extern  void * ypproc_push_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_PULL ((u_long)8)
+extern  void * ypproc_pull_1(yprequest *, CLIENT *);
+extern  void * ypproc_pull_1_svc(yprequest *, struct svc_req *);
+#define YPOLDPROC_GET ((u_long)9)
+extern  void * ypproc_get_1(yprequest *, CLIENT *);
+extern  void * ypproc_get_1_svc(yprequest *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define YPOLDPROC_NULL ((u_long)0)
+extern  void * ypproc_null_1();
+extern  void * ypproc_null_1_svc();
+#define YPOLDPROC_DOMAIN ((u_long)1)
+extern  bool_t * ypproc_domain_1();
+extern  bool_t * ypproc_domain_1_svc();
+#define YPOLDPROC_DOMAIN_NONACK ((u_long)2)
+extern  bool_t * ypproc_domain_nonack_1();
+extern  bool_t * ypproc_domain_nonack_1_svc();
+#define YPOLDPROC_MATCH ((u_long)3)
+extern  ypresponse * ypproc_match_1();
+extern  ypresponse * ypproc_match_1_svc();
+#define YPOLDPROC_FIRST ((u_long)4)
+extern  ypresponse * ypproc_first_1();
+extern  ypresponse * ypproc_first_1_svc();
+#define YPOLDPROC_NEXT ((u_long)5)
+extern  ypresponse * ypproc_next_1();
+extern  ypresponse * ypproc_next_1_svc();
+#define YPOLDPROC_POLL ((u_long)6)
+extern  ypresponse * ypproc_poll_1();
+extern  ypresponse * ypproc_poll_1_svc();
+#define YPOLDPROC_PUSH ((u_long)7)
+extern  void * ypproc_push_1();
+extern  void * ypproc_push_1_svc();
+#define YPOLDPROC_PULL ((u_long)8)
+extern  void * ypproc_pull_1();
+extern  void * ypproc_pull_1_svc();
+#define YPOLDPROC_GET ((u_long)9)
+extern  void * ypproc_get_1();
+extern  void * ypproc_get_1_svc();
+#endif /* Old Style C */ 
+
+#endif /* !_YPV1_H_RPCGEN */
diff --git a/ypset.tproj/Makefile b/ypset.tproj/Makefile
new file mode 100644 (file)
index 0000000..7abe695
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ypset
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ypset.c
+
+OTHERSRCS = Makefile.dist Makefile.preamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ypset.tproj/Makefile.dist b/ypset.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..1cb38ca
--- /dev/null
@@ -0,0 +1,7 @@
+#      from: @(#)Makefile      5.8 (Berkeley) 7/28/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $
+
+PROG=  ypset
+NOMAN=
+
+.include <bsd.prog.mk>
diff --git a/ypset.tproj/Makefile.preamble b/ypset.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/ypset.tproj/PB.project b/ypset.tproj/PB.project
new file mode 100644 (file)
index 0000000..bbc1e0f
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (ypset.c); 
+        OTHER_SOURCES = (Makefile.dist, Makefile.preamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ypset; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ypset.tproj/ypset.c b/ypset.tproj/ypset.c
new file mode 100644 (file)
index 0000000..cddc148
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "ypset.c,v 1.3 1993/06/12 00:02:37 deraadt Exp";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+//#include <rpcsvc/yp_prot.h>
+//#include <rpcsvc/ypclnt.h>
+#include <arpa/inet.h>
+
+extern bool_t xdr_domainname();
+
+void
+usage()
+{
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\typset [-h host ] [-d domain] server\n");
+       exit(1);
+}
+
+int
+bind_tohost(sin, dom, server)
+struct sockaddr_in *sin;
+char *dom, *server;
+{
+       ypbind_setdom ypsd;
+       struct timeval tv;
+       struct hostent *hp;
+       CLIENT *client;
+       int sock;
+       u_short port;
+       int r;
+       unsigned long server_addr;
+       
+       if( (port=htons(getrpcport(server, YPPROG, YPPROC_NULL, IPPROTO_UDP))) == 0) {
+               fprintf(stderr, "%s not running ypserv.\n", server);
+               exit(1);
+       }
+
+       tv.tv_sec = 15;
+       tv.tv_usec = 0;
+       sock = RPC_ANYSOCK;
+       client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock);
+       if (client==NULL) {
+               fprintf(stderr, "RPC error: can't create YPBIND client\n");
+               return YP_YPERR;
+       }
+       client->cl_auth = authunix_create_default();
+
+       bzero(&ypsd, sizeof(struct ypbind_setdom));
+
+
+       if( (hp = gethostbyname (server)) != NULL ) {
+               /* is this the most compatible way?? */
+               bcopy(hp->h_addr_list[0], &ypsd.ypsetdom_binding.ypbind_binding_addr, 4);
+       } else if( (long)(server_addr = inet_addr (server)) == -1) {
+               fprintf(stderr, "can't find address for %s\n", server);
+               exit(1);
+       } else
+               bcopy (&server_addr, &ypsd.ypsetdom_binding.ypbind_binding_addr, 4);
+               
+       ypsd.ypsetdom_domain = dom;
+
+       bcopy(&port, ypsd.ypsetdom_binding.ypbind_binding_port, 2);
+       ypsd.ypsetdom_vers = YPVERS;
+       
+       r = clnt_call(client, YPBINDPROC_SETDOM,
+               xdr_ypbind_setdom, &ypsd, xdr_void, NULL, tv);
+       if (r != RPC_SUCCESS)
+       {
+               fprintf(stderr, "Can't ypset for domain %s: %s \n",
+                       dom, clnt_sperror(client, "setdomain"));
+               clnt_destroy(client);
+               return YP_YPERR;
+       }
+       clnt_destroy(client);
+       return 0;
+}
+
+int
+main(argc, argv)
+char **argv;
+{
+       struct sockaddr_in sin;
+       struct hostent *hent;
+       extern char *optarg;
+       extern int optind;
+       char *domainname;
+       int c;
+
+       yp_get_default_domain(&domainname);
+
+       bzero(&sin, sizeof sin);
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = htonl(0x7f000001);
+
+       while( (c=getopt(argc, argv, "h:d:")) != -1)
+               switch(c) {
+               case 'd':
+                       domainname = optarg;
+                       break;
+               case 'h':
+                       if( (sin.sin_addr.s_addr=inet_addr(optarg)) == -1) {
+                               hent = gethostbyname(optarg);
+                               if(hent==NULL) {
+                                       fprintf(stderr, "ypset: host %s unknown\n",
+                                               optarg);
+                                       exit(1);
+                               }
+                               bcopy(&hent->h_addr_list[0], &sin.sin_addr,
+                                       sizeof sin.sin_addr);
+                       }
+                       break;
+               default:
+                       usage();
+               }
+
+       if(optind + 1 != argc )
+               usage();
+
+       if (bind_tohost(&sin, domainname, argv[optind]))
+               exit(1);
+       exit(0);
+}
diff --git a/ypwhich.tproj/Makefile b/ypwhich.tproj/Makefile
new file mode 100644 (file)
index 0000000..4eb6204
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ypwhich
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ypwhich.c
+
+OTHERSRCS = Makefile.dist Makefile.preamble ypwhich.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ypwhich.tproj/Makefile.dist b/ypwhich.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..9837ebe
--- /dev/null
@@ -0,0 +1,6 @@
+#      from: @(#)Makefile      5.8 (Berkeley) 7/28/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $
+
+PROG=  ypwhich
+
+.include <bsd.prog.mk>
diff --git a/ypwhich.tproj/Makefile.preamble b/ypwhich.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dc05194
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
diff --git a/ypwhich.tproj/PB.project b/ypwhich.tproj/PB.project
new file mode 100644 (file)
index 0000000..6bbaabd
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (ypwhich.c); 
+        OTHER_SOURCES = (Makefile.dist, Makefile.preamble, ypwhich.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ypwhich; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ypwhich.tproj/ypwhich.1 b/ypwhich.tproj/ypwhich.1
new file mode 100644 (file)
index 0000000..5c466f2
--- /dev/null
@@ -0,0 +1,94 @@
+.\"
+.\" Copyright (c) 1994 Christopher G. Demetriou
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"      This product includes software developed by Christopher G. Demetriou.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\"    $Id: ypwhich.1,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $
+.\"
+.Dd February 23, 1994
+.Dt YPWHICH 1
+.Os
+.Sh NAME
+.Nm ypwhich
+.Nd return hostname of YP server of map master
+.Sh SYNOPSIS
+.Nm ypwhich
+.Op Fl d Ar domain
+.Oo
+.Op Fl t
+.Fl m Op Ar mname
+|
+.Ar host
+.Oc
+.Nm ypmatch
+.Fl x
+.Sh DESCRIPTION
+.Nm Ypmatch
+tells which
+.Tn YP
+server supplies
+.Tn YP
+services to a client, or which is the master for a map.
+If invoked without arguments, it gives the
+.Tn YP
+server for the local machine.
+If
+.Ar host
+is specified, that machine is queried to find out
+which
+.Tn YP
+server it is using.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domain
+Specify a domain other than the default domain.
+.It Fl t
+Inhibit translation of map nicknames
+to their corresponding map names.
+.It Fl m Op Ar mname
+Find the master
+.Tn YP
+server for the named map.  No
+.Ar host
+may be specified with the
+.Fl m
+option.
+.Ar Mname
+can be a map name or nickname.  If
+.Ar mname
+is ommitted,
+.Nm ypwhich
+will produce a list of available maps.
+.It Fl x
+Display the map nickname table.
+.El
+.Sh SEE ALSO
+.Xr ypset 8 ,
+.Xr yp 8
+.Sh AUTHOR
+Theo De Raadt
diff --git a/ypwhich.tproj/ypwhich.c b/ypwhich.tproj/ypwhich.c
new file mode 100644 (file)
index 0000000..523e1d0
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$Id: ypwhich.c,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+//#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+extern bool_t xdr_domainname();
+
+struct ypalias {
+       char *alias, *name;
+} ypaliases[] = {
+       { "passwd", "passwd.byname" },
+       { "group", "group.byname" },
+       { "networks", "networks.byaddr" },
+       { "hosts", "hosts.byaddr" },
+       { "protocols", "protocols.bynumber" },
+       { "services", "services.byname" },
+       { "aliases", "mail.aliases" },
+       { "ethers", "ethers.byname" },
+};
+static int n_aliases = 8;
+
+void
+usage()
+{
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\typwhich [-d domain] [[-t] -m [mname] | host]\n");
+       fprintf(stderr, "\typwhich -x\n");
+       exit(1);
+}
+
+
+/*
+ * Like yp_bind except can query a specific host
+ */
+int
+bind_host(char *dom, struct sockaddr_in *sin)
+{
+       struct hostent *hent = NULL;
+       struct ypbind_resp ypbr;
+       struct timeval tv;
+       CLIENT *client;
+       int sock, r;
+       struct in_addr addr;
+
+       sock = RPC_ANYSOCK;
+       tv.tv_sec = 15;
+       tv.tv_usec = 0;
+       client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock);
+       if (client==NULL)
+       {
+               fprintf(stderr, "can't clntudp_create: %s\n",
+                       yperr_string(YPERR_YPBIND));
+               return YPERR_YPBIND;
+       }
+
+       tv.tv_sec = 5;
+       tv.tv_usec = 0;
+       r = clnt_call(client, YPBINDPROC_DOMAIN,
+               xdr_domainname, &dom, xdr_ypbind_resp, &ypbr, tv);
+
+       if (r != RPC_SUCCESS)
+       {
+               fprintf(stderr, "can't clnt_call: %s\n", yperr_string(YPERR_YPBIND));
+               clnt_destroy(client);
+               return YPERR_YPBIND;
+       }
+       else
+       {
+               if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
+               {
+                       fprintf(stderr, "can't yp_bind: Reason: %s\n",
+                               yperr_string(ypbr.ypbind_status));
+                       clnt_destroy(client);
+                       return r;
+               }
+       }
+       
+       clnt_destroy(client);
+
+       memmove(&addr, ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 4);
+
+       hent = gethostbyaddr((char *)&(addr.s_addr), sizeof(u_long), AF_INET);
+       if (hent != NULL) printf("%s\n", hent->h_name);
+       else printf("%s\n", inet_ntoa(addr));
+       return 0;
+}
+       
+int
+main(int argc, char *argv[])
+{
+       char *domainname, *master, *map;
+       ypmaplist *ypml, *y;
+       extern char *optarg;
+       extern int optind;
+       struct hostent *hent;
+       struct sockaddr_in sin;
+       int notrans, mode, getmap;
+       int c, r, i;
+
+       yp_get_default_domain(&domainname);
+
+       map = NULL;
+       getmap = notrans = mode = 0;
+       while ((c = getopt(argc, argv, "xd:mt")) != -1)
+       {
+               switch(c)
+               {
+                       case 'x':
+                               for (i = 0; i < n_aliases; i++)
+                               {
+                                       printf("Use \"%s\" for \"%s\"\n",
+                                               ypaliases[i].alias,
+                                               ypaliases[i].name);
+                               }
+                               exit(0);
+
+                       case 'd':
+                               domainname = optarg;
+                               break;
+
+                       case 't':
+                               notrans++;
+                               break;
+
+                       case 'm':
+                               mode++;
+                               break;
+
+                       default:
+                               usage();
+               }
+       }
+
+       if (mode == 0)
+       {
+               switch(argc-optind)
+               {
+                       case 0:
+                               bzero(&sin, sizeof sin);
+                               sin.sin_family = AF_INET;
+                               sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+                               if (bind_host(domainname, &sin)) exit(1);
+                               break;
+
+                       case 1:
+                               bzero(&sin, sizeof sin);
+                               sin.sin_family = AF_INET;
+                               sin.sin_addr.s_addr = inet_addr(argv[optind]);
+                               if (sin.sin_addr.s_addr == -1)
+                               {
+                                       hent = gethostbyname(argv[optind]);
+                                       if (hent == NULL)
+                                       {
+                                               fprintf(stderr, "ypwhich: host %s unknown\n",
+                                                       argv[optind]);
+                                               exit(1);
+                                       }
+
+                                       bcopy((char *)hent->h_addr_list[0],
+                                               (char *)&sin.sin_addr, sizeof sin.sin_addr);
+                               }
+
+                               if (bind_host(domainname, &sin)) exit(1);
+                               break;
+                               
+                       default:
+                               usage();
+               }
+               
+               exit(0);
+       }
+
+       if (argc-optind > 1) usage();
+
+       if (argv[optind])
+       {
+               map = argv[optind];
+               for (i = 0; (!notrans) && (i < n_aliases); i++)
+               {
+                       if (!strcmp(map, ypaliases[i].alias)) map = ypaliases[i].name;
+               }
+               
+               r = yp_master(domainname, map, &master);
+               switch(r)
+               {
+                       case 0:
+                               printf("%s\n", master);
+                               free(master);
+                               break;
+                       case YPERR_YPBIND:
+                               fprintf(stderr, "ypwhich: not running ypbind\n");
+                               exit(1);
+                       default:
+                               fprintf(stderr, "Can't find master for map %s. Reason: %s\n",
+                                       map, yperr_string(r));
+                               exit(1);
+                       }
+                       exit(0);
+               }
+
+               ypml = NULL;
+               r = yp_maplist(domainname, &ypml);
+               switch(r)
+               {
+                       case 0:
+                               while (ypml != NULL)
+                               {
+                                       r = yp_master(domainname, ypml->map, &master);
+                                       switch(r)
+                                       {
+                                               case 0:
+                                                       printf("%s %s\n", ypml->map, master);
+                                                       free(master);
+                                                       break;
+                                               default:
+                                                       fprintf(stderr,
+                                                               "YP: can't find the master of %s: Reason: %s\n",
+                                                               ypml->map, yperr_string(r));
+                                                       break;
+                                       }
+
+                                       y = ypml;
+                                       ypml = ypml->next;
+                                       free(y);
+                               }
+                               break;
+
+                       case YPERR_YPBIND:
+                               fprintf(stderr, "ypwhich: not running ypbind\n");
+                               exit(1);
+                               
+                       default:
+                               fprintf(stderr, "Can't get map list for domain %s. Reason: %s\n",
+                                       domainname, yperr_string(r));
+                               exit(1);
+               }
+
+       exit(0);
+}
diff --git a/ypxfr.tproj/Makefile b/ypxfr.tproj/Makefile
new file mode 100644 (file)
index 0000000..bec2e2c
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = ypxfr
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = ypdb.h ypdef.h yplib_host.h yplog.h
+
+CFILES = ypdb.c yplib_host.c yplog.c ypxfr.c ypxfr_xdr.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
+            ypxfr_1perday.sh ypxfr_1perhour.sh ypxfr_2perday.sh ypxfr.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ypxfr.tproj/Makefile.postamble b/ypxfr.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..509e7f5
--- /dev/null
@@ -0,0 +1,101 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+STRIPFLAGS =
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
diff --git a/ypxfr.tproj/Makefile.preamble b/ypxfr.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..83f25c7
--- /dev/null
@@ -0,0 +1,123 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. <<default?>>
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSION: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
diff --git a/ypxfr.tproj/PB.project b/ypxfr.tproj/PB.project
new file mode 100644 (file)
index 0000000..1371c2f
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (ypdb.h, ypdef.h, yplib_host.h, yplog.h); 
+        LIBRARYSEARCH = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (ypdb.c, yplib_host.c, yplog.c, ypxfr.c, ypxfr_xdr.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            ypxfr_1perday.sh, 
+            ypxfr_1perhour.sh, 
+            ypxfr_2perday.sh, 
+            ypxfr.8
+        ); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ypxfr; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ypxfr.tproj/ypdb.c b/ypxfr.tproj/ypdb.c
new file mode 100644 (file)
index 0000000..c9bd178
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ypdb.h"
+
+#ifdef YPDB_PATCH
+extern DBM *__hash_open();
+#else
+extern DBM *__bt_open();
+#endif
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+       char path[MAXPATHLEN];
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       char path[MAXPATHLEN];
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX);
+       db = (DBM *)__bt_open(path, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+
+extern DBM *
+ypdb_open_suf(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+#ifdef YPDB_PATCH
+       HASHINFO info;
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = NULL;
+       info.hash = NULL;
+       info.lorder = 0;
+       return ((DBM *)__hash_open(file, flags, mode, &info, 0));
+#else
+       BTREEINFO info;
+       DBM *db;
+
+       info.flags = 0;
+       info.cachesize = 0;
+       info.maxkeypage = 0;
+       info.minkeypage = 0;
+       info.psize = 0;
+       info.compare = NULL;
+       info.prefix = NULL;
+       info.lorder = 0;
+       db = (DBM *)__bt_open(file, flags, mode, &info, 0);
+       return (db);
+#endif
+}
+
+extern void
+ypdb_close(db)
+       DBM *db;
+{
+       (void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_fetch(db, key)
+       DBM *db;
+       datum key;
+{
+       datum retval;
+       int status;
+
+       status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+       if (status) {
+               retval.dptr = NULL;
+               retval.dsize = 0;
+       }
+       return (retval);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_firstkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_nextkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+
+extern datum
+ypdb_setkey(db, key)
+       DBM *db;
+        datum key;
+{
+       int status;
+       datum retdata;
+#ifdef YPDB_PATCH
+       datum retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       while ((retkey.dptr != NULL) &&
+              ((retkey.dsize != key.dsize) ||
+               (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) {
+         status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+         if (status)
+               retkey.dptr = NULL;
+       };
+       return (retkey);
+#else
+       status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR);
+       if (status)
+               key.dptr = NULL;
+       return (key);
+#endif
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ */
+
+int
+ypdb_delete(db, key)
+       DBM *db;
+       datum key;
+{
+       int status;
+
+       status = (db->del)(db, (DBT *)&key, 0);
+       if (status)
+               return (-1);
+       else
+               return (0);
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ *      1 if YPDB_INSERT and entry exists
+ */
+
+int
+ypdb_store(db, key, content, flags)
+       DBM *db;
+       datum key, content;
+       int flags;
+{
+       return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+           (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0));
+}
+
diff --git a/ypxfr.tproj/ypdb.h b/ypxfr.tproj/ypdb.h
new file mode 100644 (file)
index 0000000..9afbad5
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * This code is derived from ndbm module of BSD4.4 db (hash) by
+ * Mats O Jansson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDB_H_
+#define _YPDB_H_
+
+#ifndef _DB_H_
+#include <bsd/db.h>
+#endif
+
+#define YPDB_SUFFIX    ".db"
+
+/* Flags to ypdb_store(). */
+#define YPDB_INSERT      0
+#define YPDB_REPLACE     1
+
+#ifndef DATUM
+typedef struct {
+       char    *dptr;
+       int     dsize;
+} datum;
+#define DATUM
+#endif
+
+typedef DB DBM;
+
+__BEGIN_DECLS
+void    ypdb_close __P((DBM *));
+datum   ypdb_fetch __P((DBM *, datum));
+datum   ypdb_firstkey __P((DBM *));
+datum   ypdb_nextkey __P((DBM *));
+datum   ypdb_setkey __P((DBM *, datum));
+DBM     *ypdb_open __P((const char *, int, int));
+DBM     *ypdb_open_suf __P((const char *, int, int));
+int     ypdb_store __P((DBM *, datum, datum, int));
+__END_DECLS
+
+#endif /* !_YPDB_H_ */
diff --git a/ypxfr.tproj/ypdef.h b/ypxfr.tproj/ypdef.h
new file mode 100644 (file)
index 0000000..89970d7
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPDEF_H_
+#define _YPDEF_H_
+
+#define YP_DB_PATH "/var/yp"
+#define YP_LAST_KEY        "YP_LAST_MODIFIED"
+#define YP_LAST_LEN       (sizeof(YP_LAST_KEY)-1)
+#define YP_INPUT_KEY       "YP_INPUT_FILE"
+#define YP_INPUT_LEN      (sizeof(YP_INPUT_KEY)-1)
+#define YP_OUTPUT_KEY      "YP_OUTPUT_FILE"
+#define YP_OUTPUT_LEN     (sizeof(YP_OUTPUT_KEY)-1)
+#define YP_MASTER_KEY      "YP_MASTER_NAME"
+#define YP_MASTER_LEN     (sizeof(YP_MASTER_KEY)-1)
+#define YP_DOMAIN_KEY      "YP_DOMAIN_NAME"
+#define YP_DOMAIN_LEN     (sizeof(YP_DOMAIN_KEY)-1)
+#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN"
+#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1)
+#define YP_SECURE_KEY      "YP_SECURE"
+#define YP_SECURE_LEN      (sizeof(YP_SECURE_KEY)-1)
+
+#define MAX_LAST_LEN 10
+#define MAX_MASTER_LEN 255
+#define YP_HOSTNAME "hosts.byname"
+#define YP_HOSTADDR "hosts.byaddr"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define YPXFR_PROC "/usr/sbin/ypxfr"
+#define YPPUSH_PROC "/usr/sbin/yppush"
+#define YPSERV_PID_PATH "/var/run/ypserv.pid"
+#define YP_SECURENET_FILE "/var/yp/securenet"
+
+#endif /* !_YPDEF_H_ */
diff --git a/ypxfr.tproj/yplib_host.c b/ypxfr.tproj/yplib_host.c
new file mode 100644 (file)
index 0000000..70b914b
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char *rcsid = "$OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+extern bool_t xdr_domainname(), xdr_ypbind_resp();
+extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
+extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val();
+extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq();
+extern bool_t xdr_ypresp_master();
+
+extern int (*ypresp_allfn)();
+extern void *ypresp_data;
+
+int _yplib_host_timeout = 10;
+
+CLIENT *
+yp_bind_host(server,program,version,port,usetcp)
+char *server;
+u_long program,version;
+u_short port;
+int usetcp;
+{
+       struct sockaddr_in rsrv_sin;
+       int rsrv_sock;
+       struct hostent *h;
+       struct timeval tv;
+       static CLIENT *client;
+
+       memset(&rsrv_sin, 0, sizeof rsrv_sin);
+       rsrv_sin.sin_len = sizeof rsrv_sin;
+       rsrv_sin.sin_family = AF_INET;
+       rsrv_sock = RPC_ANYSOCK;
+       if (port != 0) {
+               rsrv_sin.sin_port = htons(port);
+       }
+
+       if ((*server >= '0') && (*server <= '9')) {
+               if(inet_aton(server,&rsrv_sin.sin_addr) == 0) {
+                       fprintf(stderr, "inet_aton: invalid address %s.\n",
+                               server);
+                       exit(1);
+               }
+       } else {
+               h = gethostbyname(server);
+               if(h == NULL) {
+                       fprintf(stderr, "gethostbyname: unknown host %s.\n",
+                               server);
+                       exit(1);
+               }
+               rsrv_sin.sin_addr.s_addr = *(u_int32_t *)h->h_addr;
+       }
+
+       tv.tv_sec = 10;
+       tv.tv_usec = 0;
+
+       if (usetcp) {
+               client = clnttcp_create(&rsrv_sin, program, version,
+                                       &rsrv_sock, 0, 0);
+       } else {
+               client = clntudp_create(&rsrv_sin, program, version, tv,
+                                       &rsrv_sock);
+       }
+
+       if (client == NULL) {
+               fprintf(stderr, "clntudp_create: no contact with host %s.\n",
+                       server);
+               exit(1);
+       }
+
+       return(client);
+       
+}
+
+CLIENT *
+yp_bind_local(program,version)
+u_long program,version;
+{
+       struct sockaddr_in rsrv_sin;
+       int rsrv_sock;
+       struct timeval tv;
+       static CLIENT *client;
+
+       memset(&rsrv_sin, 0, sizeof rsrv_sin);
+       rsrv_sin.sin_len = sizeof rsrv_sin;
+       rsrv_sin.sin_family = AF_INET;
+       rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       rsrv_sock = RPC_ANYSOCK;
+
+       tv.tv_sec = 10;
+       tv.tv_usec = 0;
+
+       client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock);
+       if (client == NULL) {
+               fprintf(stderr,"clntudp_create: no contact with localhost.\n");
+               exit(1);
+       }
+
+       return(client);
+       
+}
+
+int
+yp_match_host(client, indomain, inmap, inkey, inkeylen, outval, outvallen)
+CLIENT *client;
+char *indomain;
+char *inmap;
+const char *inkey;
+int inkeylen;
+char **outval;
+int *outvallen;
+{
+       struct ypresp_val yprv;
+       struct timeval tv;
+       struct ypreq_key yprk;
+       int r;
+
+       *outval = NULL;
+       *outvallen = 0;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprk.domain = indomain;
+       yprk.map = inmap;
+       yprk.key.keydat_val = (char *)inkey;
+       yprk.key.keydat_len = inkeylen;
+
+       memset(&yprv, 0, sizeof yprv);
+
+       r = clnt_call(client, YPPROC_MATCH,
+               xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_match_host: clnt_call");
+       }
+       if( !(r=ypprot_err(yprv.stat)) ) {
+               *outvallen = yprv.val.valdat_len;
+               *outval = (char *)malloc(*outvallen+1);
+               memcpy(*outval, yprv.val.valdat_val, *outvallen);
+               (*outval)[*outvallen] = '\0';
+       }
+       xdr_free(xdr_ypresp_val, (char *)&yprv);
+       return r;
+}
+
+int
+yp_first_host(client, indomain, inmap, outkey, outkeylen, outval, outvallen)
+CLIENT *client;
+char *indomain;
+char *inmap;
+char **outkey;
+int *outkeylen;
+char **outval;
+int *outvallen;
+{
+       struct ypresp_key_val yprkv;
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       int r;
+
+       *outkey = *outval = NULL;
+       *outkeylen = *outvallen = 0;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+       memset(&yprkv, 0, sizeof yprkv);
+
+       r = clnt_call(client, YPPROC_FIRST,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_first_host: clnt_call");
+       }
+       if( !(r=ypprot_err(yprkv.stat)) ) {
+               *outkeylen = yprkv.key.keydat_len;
+               *outkey = (char *)malloc(*outkeylen+1);
+               memcpy(*outkey, yprkv.key.keydat_val, *outkeylen);
+               (*outkey)[*outkeylen] = '\0';
+               *outvallen = yprkv.val.valdat_len;
+               *outval = (char *)malloc(*outvallen+1);
+               memcpy(*outval, yprkv.val.valdat_val, *outvallen);
+               (*outval)[*outvallen] = '\0';
+       }
+       xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
+       return r;
+}
+
+int
+yp_next_host(client, indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen)
+CLIENT *client;
+char *indomain;
+char *inmap;
+char *inkey;
+int inkeylen;
+char **outkey;
+int *outkeylen;
+char **outval;
+int *outvallen;
+{
+       struct ypresp_key_val yprkv;
+       struct ypreq_key yprk;
+       struct timeval tv;
+       int r;
+
+       *outkey = *outval = NULL;
+       *outkeylen = *outvallen = 0;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprk.domain = indomain;
+       yprk.map = inmap;
+       yprk.key.keydat_val = inkey;
+       yprk.key.keydat_len = inkeylen;
+       memset(&yprkv, 0, sizeof yprkv);
+
+       r = clnt_call(client, YPPROC_NEXT,
+               xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_next_host: clnt_call");
+       }
+       if( !(r=ypprot_err(yprkv.stat)) ) {
+               *outkeylen = yprkv.key.keydat_len;
+               *outkey = (char *)malloc(*outkeylen+1);
+               memcpy(*outkey, yprkv.key.keydat_val, *outkeylen);
+               (*outkey)[*outkeylen] = '\0';
+               *outvallen = yprkv.val.valdat_len;
+               *outval = (char *)malloc(*outvallen+1);
+               memcpy(*outval, yprkv.val.valdat_val, *outvallen);
+               (*outval)[*outvallen] = '\0';
+       }
+       xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
+       return r;
+}
+
+int
+yp_all_host(client, indomain, inmap, incallback)
+CLIENT *client;
+char *indomain;
+char *inmap;
+struct ypall_callback *incallback;
+{
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       u_long status;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+       ypresp_allfn = incallback->foreach;
+       ypresp_data = (void *)incallback->data;
+
+       (void) clnt_call(client, YPPROC_ALL,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv);
+       xdr_free(xdr_ypresp_all_seq, (char *)&status);  /* not really needed... */
+
+       if(status != YP_FALSE)
+               return ypprot_err(status);
+       return 0;
+}
+
+int
+yp_order_host(client, indomain, inmap, outorder)
+CLIENT *client;
+char *indomain;
+char *inmap;
+u_int32_t *outorder;
+{
+       struct ypresp_order ypro;
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       int r;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+
+       memset(&ypro, 0, sizeof ypro);
+
+       r = clnt_call(client, YPPROC_ORDER,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_order_host: clnt_call");
+       }
+
+       *outorder = ypro.ordernum;
+       xdr_free(xdr_ypresp_order, (char *)&ypro);
+       return ypprot_err(ypro.stat);
+}
+
+int
+yp_master_host(client, indomain, inmap, outname)
+CLIENT *client;
+char *indomain;
+char *inmap;
+char **outname;
+{
+       struct ypresp_master yprm;
+       struct ypreq_nokey yprnk;
+       struct timeval tv;
+       int r;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       yprnk.domain = indomain;
+       yprnk.map = inmap;
+
+       memset(&yprm, 0, sizeof yprm);
+
+       r = clnt_call(client, YPPROC_MASTER,
+               xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_master: clnt_call");
+       }
+       if( !(r=ypprot_err(yprm.stat)) ) {
+               *outname = (char *)strdup(yprm.peer);
+       }
+       xdr_free(xdr_ypresp_master, (char *)&yprm);
+       return r;
+}
+
+int
+yp_maplist_host(client, indomain, outmaplist)
+CLIENT *client;
+char *indomain;
+struct ypmaplist **outmaplist;
+{
+       struct ypresp_maplist ypml;
+       struct timeval tv;
+       int r;
+
+       tv.tv_sec = _yplib_host_timeout;
+       tv.tv_usec = 0;
+
+       memset(&ypml, 0, sizeof ypml);
+
+       r = clnt_call(client, YPPROC_MAPLIST,
+               xdr_domainname, &indomain, xdr_ypresp_maplist, &ypml, tv);
+       if (r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_maplist: clnt_call");
+       }
+       *outmaplist = ypml.maps;
+       /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/
+       return ypprot_err(ypml.stat);
+}
+
diff --git a/ypxfr.tproj/yplib_host.h b/ypxfr.tproj/yplib_host.h
new file mode 100644 (file)
index 0000000..038fb68
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplib_host.h,v 1.4 1997/05/01 22:14:45 niklas Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Theo de Raadt.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPLIB_HOST_H_
+#define _YPLIB_HOST_H_
+
+int    yp_match_host   __P((CLIENT *client, char *indomain, char *inmap,
+                           const char *inkey, int inkeylen, char **outval,
+                           int *outvallen));
+int    yp_first_host   __P((CLIENT *client, char *indomain, char *inmap,
+                           char **outkey, int *outkeylen, char **outval,
+                           int *outvallen));
+int    yp_next_host    __P((CLIENT *client, char *indomain, char *inmap,
+                           char *inkey, int inkeylen, char **outkey,
+                           int *outkeylen, char **outval, int *outvallen));
+int    yp_master_host  __P((CLIENT *client,
+                           char *indomain, char *inmap, char **outname));
+int    yp_order_host   __P((CLIENT *client,
+                           char *indomain, char *inmap, u_int32_t *outorder));
+int    yp_all_host     __P((CLIENT *client, char *indomain, char *inmap,
+                           struct ypall_callback *incallback));
+int    yp_maplist_host __P((CLIENT *client, char *indomain,
+                           struct ypmaplist **outmaplist));
+CLIENT *yp_bind_local  __P((u_long program, u_long version));
+CLIENT *yp_bind_host   __P((char *server, u_long program, u_long version,
+                           u_short port, int usetcp));
+
+#endif /* _YPLIB_HOST_H_ */
+
diff --git a/ypxfr.tproj/yplog.c b/ypxfr.tproj/yplog.c
new file mode 100644 (file)
index 0000000..3460c9a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplog.c,v 1.5 1997/08/09 22:44:04 maja Exp $ */
+
+/*
+ * Copyright (c) 1996 Charles D. Cranor
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Charles D. Cranor.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * yplog.c: replacement yplog routines for 
+ * Mats O Jansson's ypserv program, as added by
+ * Chuck Cranor.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "yplog.h"
+
+static FILE    *logfp = NULL;          /* the log file */
+
+/*
+ * yplog(): like a printf, but to the log file.   does the flush
+ * and data for you.
+ */
+
+void
+#ifdef __STDC__
+yplog(const char *fmt, ...)
+#else
+yplog(fmt, va_alist)
+       char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+#ifdef __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       vyplog(fmt, ap);
+       va_end(ap);
+}
+
+/*
+ * vyplog() support routine for yplog()
+ */
+
+void
+vyplog(fmt, ap)
+       register const char *fmt;
+       va_list ap;
+{
+        time_t t;
+
+       if (logfp == NULL)
+               return;
+       (void)time(&t);
+       fprintf(logfp,"%.15s ", ctime(&t) + 4);
+       vfprintf(logfp, fmt, ap);
+       fprintf(logfp,"\n");
+       fflush(logfp);
+}
+
+/*
+ * open log
+ */
+
+void
+ypopenlog()
+{
+       static char logfn[] = "/var/yp/ypserv.log";
+
+       if (access(logfn, W_OK) == -1)
+               return;
+       logfp = fopen("/var/yp/ypserv.log", "a");
+       if (logfp == NULL)
+               return;
+       yplog("yplog opened");
+}
+
+/*
+ * close log
+ */
+
+void
+ypcloselog()
+{
+       if (logfp) {
+               yplog("yplog closed");
+               fclose(logfp);
+               logfp = NULL;
+       }
+}
diff --git a/ypxfr.tproj/yplog.h b/ypxfr.tproj/yplog.h
new file mode 100644 (file)
index 0000000..dd9d6fb
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: yplog.h,v 1.3 1996/05/30 09:53:04 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _YPLOG_H_
+#define _YPLOG_H_
+
+__BEGIN_DECLS
+void    yplog __P((const char *, ...));
+void    vyplog __P((const char *, _BSD_VA_LIST_));
+void   ypopenlog __P((void));
+void   ypcloselog __P((void));
+__END_DECLS
+
+#endif /* !_YPLOG_H_ */
diff --git a/ypxfr.tproj/ypxfr.8 b/ypxfr.tproj/ypxfr.8
new file mode 100644 (file)
index 0000000..5a78dad
--- /dev/null
@@ -0,0 +1,92 @@
+.\"    $OpenBSD: ypxfr.8,v 1.5 1997/04/20 10:08:35 maja Exp $
+.\" Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    $OpenBSD: ypxfr.8,v 1.5 1997/04/20 10:08:35 maja Exp $
+.\"
+.Dd August 18, 1994
+.Dt YPXFR 8
+.Os
+.Sh NAME
+.Nm ypxfr
+.Nd get a YP map from YP server
+.Sh SYNOPSIS
+.Nm ypxfr
+.Op Fl bcf
+.Op Fl d Ar domain
+.Op Fl h Ar host
+.Op Fl s Ar domain
+.Op Fl C Ar tid prog ipadd port
+.Ar mapname
+.Sh DESCRIPTION
+.Nm ypxfr 
+is the utiliy in YP that transfers maps to the local host.
+.Pp
+Since the YP master transfers a map when it has changed, an YP slave should
+check for missed maps regulary. This can be done via an entry in
+.Xr crontab 5 .
+The scripts
+.Ar ypxfr_1perhour , ypxfr_2perday
+and
+.Ar ypxfr_1perday
+could be used for that.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl b
+Preserve the entry in the database informing a YP server to use
+DNS to get information about unknown hosts. This option will only have
+effect on the two maps hosts.byname and hosts.byaddr.
+.It Fl c
+Don't send a "Clear current map" to local ypserv process. Useful if ypserv
+isn't running localy to avoid timeout message. 
+.It Fl f 
+Force map transfer, even if version of master is older than local copy.
+.It Fl d Ar domain
+Don't use default domain, use the specifiyed domain.
+.It Fl h Ar host
+Get map from host insteed of the maps master host.
+.It Fl s Ar domain
+Specify a source domain other than the target domain.
+.It Fl C Ar tid prog ipadd port
+This option is only used by ypserv. This is to open communication with
+an yppush on another host.
+.El
+.Sh FILES
+.Bl -tag -width /usr/sbin/ypxfr_1perhour -compact
+.It Pa /usr/sbin/ypxfr_1perhour
+.It Pa /usr/sbin/ypxfr_2perday
+.It Pa /usr/sbin/ypxfr_1perday
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr yppush 8 ,
+.Xr ypserv 8 
+.Sh AUTHOR
+Mats O Jansson <moj@stacken.kth.se>
diff --git a/ypxfr.tproj/ypxfr.c b/ypxfr.tproj/ypxfr.c
new file mode 100644 (file)
index 0000000..faa88bf
--- /dev/null
@@ -0,0 +1,668 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypxfr.c,v 1.22 1997/07/30 12:07:02 maja Exp $ */
+
+/*
+ * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: ypxfr.c,v 1.22 1997/07/30 12:07:02 maja Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "yplib_host.h"
+#include "yplog.h"
+#include "ypdb.h"
+#include "ypdef.h"
+
+extern char *__progname;               /* from crt0.o */
+DBM    *db;
+
+extern bool_t xdr_ypresp_all_seq();
+
+extern int (*ypresp_allfn)();
+extern void *ypresp_data;
+
+static int
+ypxfr_foreach(status,keystr,keylen,valstr,vallen,data)
+int status,keylen,vallen;
+char *keystr,*valstr,*data;
+{
+       datum   key,val;
+
+       if (status == YP_NOMORE)
+               return(0);
+
+       keystr[keylen] = '\0';
+       valstr[vallen] = '\0';
+
+       key.dptr = keystr;
+       key.dsize = strlen(keystr);
+
+       val.dptr = valstr;
+       val.dsize = strlen(valstr);
+       
+       ypdb_store(db, key, val, YPDB_INSERT);
+
+       return 0;
+}
+
+int
+get_local_ordernum(domain, map, lordernum)
+char *domain;
+char *map;
+u_int32_t *lordernum;
+{
+       char map_path[MAXPATHLEN];
+       char order_key[] = YP_LAST_KEY;
+       char order[MAX_LAST_LEN+1];
+       struct stat finfo;
+       DBM *db;
+       datum k,v;
+       int status;
+
+       /* This routine returns YPPUSH_SUCC or YPPUSH_NODOM */
+       
+       status = YPPUSH_SUCC;
+       
+       snprintf(map_path, sizeof map_path, "%s/%s", YP_DB_PATH, domain);
+       if (!((stat(map_path, &finfo) == 0) &&
+             ((finfo.st_mode & S_IFMT) == S_IFDIR))) {
+               fprintf(stderr, "%s: domain %s not found locally\n",
+                   __progname, domain);
+               status = YPPUSH_NODOM;
+       }
+
+       if(status > 0) {
+               snprintf(map_path, sizeof map_path, "%s/%s/%s%s",
+                   YP_DB_PATH, domain, map, YPDB_SUFFIX);
+               if(!(stat(map_path, &finfo) == 0)) {
+                       status = YPPUSH_NOMAP;
+               }
+       }
+       
+       if(status > 0) {
+               snprintf(map_path, sizeof map_path, "%s/%s/%s",
+                   YP_DB_PATH, domain, map);
+               db = ypdb_open(map_path, O_RDONLY, 0444);
+               if(db == NULL) {
+                       status = YPPUSH_DBM;
+               }
+               
+       }
+               
+       if(status > 0) {
+               k.dptr = (char *)&order_key;
+               k.dsize = YP_LAST_LEN;
+
+               v = ypdb_fetch(db,k);
+               ypdb_close(db);
+               
+               if (v.dptr == NULL) {
+                       *lordernum = 0;
+               } else {
+                       strncpy(order, v.dptr, sizeof order-1);
+                       order[sizeof order-1] = '\0';
+                       *lordernum = (u_int32_t)atol(order);
+               }
+       }
+
+       if((status == YPPUSH_NOMAP) || (status == YPPUSH_DBM)) {
+               *lordernum = 0;
+               status = YPPUSH_SUCC;
+       }
+
+       return(status);
+
+}
+
+int
+get_remote_ordernum(client, domain, map, lordernum, rordernum)
+CLIENT *client;
+char *domain;
+char *map;
+u_int32_t lordernum;
+u_int32_t *rordernum;
+{
+       int status;
+
+       status = yp_order_host(client, domain, map, rordernum);
+
+       if (status == 0) {
+               if(*rordernum <= lordernum) {
+                       status = YPPUSH_AGE;
+               } else {
+                       status = YPPUSH_SUCC;
+               }
+       } 
+
+       return status;
+}
+
+void
+get_map(client,domain,map,incallback)
+CLIENT *client;
+char *domain;
+char *map;
+struct ypall_callback *incallback;
+{
+       (void)yp_all_host(client, domain, map, incallback);
+               
+}
+
+DBM *
+create_db(domain,map,temp_map)
+char *domain;
+char *map;
+char *temp_map;
+{
+       return ypdb_open_suf(temp_map, O_RDWR, 0444);
+}
+
+int
+install_db(domain,map,temp_map)
+char *domain;
+char *map;
+char *temp_map;
+{
+       char    db_name[MAXPATHLEN];
+
+       snprintf(db_name, sizeof db_name, "%s/%s/%s%s",
+           YP_DB_PATH, domain, map, YPDB_SUFFIX);
+       rename(temp_map, db_name);
+
+       return YPPUSH_SUCC;
+}
+
+int
+add_order(db, ordernum)
+DBM *db;
+u_int32_t ordernum;
+{
+       char    datestr[11];
+       datum   key,val;
+       char    keystr[] = YP_LAST_KEY;
+       int     status;
+
+       sprintf(datestr, "%010u", ordernum);
+
+       key.dptr = keystr;
+       key.dsize = strlen(keystr);
+       
+       val.dptr = datestr;
+       val.dsize = strlen(datestr);
+       
+       status = ypdb_store(db, key, val, YPDB_INSERT);
+       if(status >= 0) {
+               status = YPPUSH_SUCC;
+       } else {
+               status = YPPUSH_DBM;
+       }
+       return(status);
+}
+
+int
+add_master(client, domain, map, db)
+CLIENT *client;
+char *domain;
+char *map;
+DBM *db;
+{
+       char    keystr[] = YP_MASTER_KEY;
+       char    *master;
+       int     status;
+       datum   key,val;
+
+       master = NULL;
+
+       /* Get MASTER */
+
+       status = yp_master_host(client, domain, map, &master);
+       
+       if(master != NULL) {
+         key.dptr = keystr;
+         key.dsize = strlen(keystr);
+         
+         val.dptr = master;
+         val.dsize = strlen(master);
+       
+         status = ypdb_store(db, key, val, YPDB_INSERT);
+         if(status >= 0) {
+               status = YPPUSH_SUCC;
+         } else {
+               status = YPPUSH_DBM;
+         }
+       }
+
+       return status;
+}
+
+int
+add_interdomain(client, domain, map, db)
+CLIENT *client;
+char *domain;
+char *map;
+DBM *db;
+{
+       char    keystr[] = YP_INTERDOMAIN_KEY;
+       char    *value;
+       int     vallen;
+       int     status;
+       datum   k,v;
+
+       /* Get INTERDOMAIN */
+
+       k.dptr = keystr;
+       k.dsize = strlen(keystr);
+
+       status = yp_match_host(client, domain, map,
+                              k.dptr, k.dsize, &value, &vallen);
+       
+       if(status == 0 && value) {
+               v.dptr = value;
+               v.dsize = vallen;
+               
+               if(v.dptr != NULL) {
+                       status = ypdb_store(db,k,v,YPDB_INSERT);
+                       if(status >= 0) {
+                               status = YPPUSH_SUCC;
+                       } else {
+                               status = YPPUSH_DBM;
+                       }
+               }
+       }
+
+       return 1;
+}
+
+int
+add_secure(client, domain, map, db)
+CLIENT *client;
+char *domain;
+char *map;
+DBM *db;
+{
+       char    keystr[] = YP_SECURE_KEY;
+       char    *value;
+       int     vallen;
+       int     status;
+       datum   k,v;
+
+       /* Get SECURE */
+
+       k.dptr = keystr;
+       k.dsize = strlen(keystr);
+
+       status = yp_match_host(client, domain, map,
+                              k.dptr, k.dsize, &value, &vallen);
+       
+       if(status > 0) {
+               v.dptr = value;
+               v.dsize = vallen;
+               
+               if(v.dptr != NULL) {
+                       status = ypdb_store(db,k,v,YPDB_INSERT);
+                       if(status >= 0) {
+                               status = YPPUSH_SUCC;
+                       } else {
+                               status = YPPUSH_DBM;
+                       }
+               }
+       }
+
+       return status;
+
+}
+
+int
+send_clear(client)
+CLIENT *client;
+{
+       struct  timeval tv;
+       int     r;
+       int     status;
+
+       status = YPPUSH_SUCC;
+
+       tv.tv_sec = 10;
+       tv.tv_usec = 0;
+
+       /* Send CLEAR */
+
+       r = clnt_call(client, YPPROC_CLEAR,
+                     xdr_void, 0, xdr_void, 0, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yp_clear: clnt_call");
+       }
+
+       return status;
+
+}
+
+int
+send_reply(client,status,tid)
+CLIENT *client;
+u_long status;
+u_long  tid;
+{
+       struct  timeval tv;
+       struct  ypresp_xfr resp;
+       int     r;
+
+       tv.tv_sec = 10;
+       tv.tv_usec = 0;
+
+       resp.transid = tid;
+       resp.xfrstat = status;
+
+       /* Send CLEAR */
+
+       r = clnt_call(client, 1,
+                     xdr_ypresp_xfr, &resp, xdr_void, 0, tv);
+       if(r != RPC_SUCCESS) {
+               clnt_perror(client, "yppushresp_xdr: clnt_call");
+       }
+
+       return status;
+
+}
+
+int
+main (argc,argv)
+int argc;
+char *argv[];
+{
+       int      usage = 0;
+       int      cflag = 0;
+       int      fflag = 0;
+       int      Cflag = 0;
+       int      ch;
+       extern   char *optarg;
+       char     *domain;
+       char     *host = NULL;
+       char     *srcdomain = NULL;
+       char     *tid = NULL;
+       char     *prog = NULL;
+       char     *ipadd = NULL;
+       char     *port = NULL;
+       char     *map = NULL;
+       u_int32_t ordernum, new_ordernum;
+       struct   ypall_callback callback;
+       CLIENT   *client;
+       int      status,xfr_status;
+       int      srvport;
+       
+       status = YPPUSH_SUCC;
+       client = NULL;
+
+       yp_get_default_domain(&domain);
+
+       while ((ch = getopt(argc, argv, "cd:fh:s:C:")) != -1)
+         switch (ch) {
+         case 'c':
+           cflag++;
+           break;
+         case 'd':
+           if (strchr(optarg, '/'))    /* Ha ha, we are not listening */
+               break;
+           domain = optarg;
+           break;
+         case 'f':
+           fflag++;
+           break;
+         case 'h':
+           host = optarg;
+           break;
+         case 's':
+           if (strchr(optarg, '/'))    /* Ha ha, we are not listening */
+               break;
+           srcdomain = optarg;
+           break;
+         case 'C':
+           if (optind + 3 >= argc) {
+               usage++;
+               optind = argc;
+               break;
+           }
+           Cflag++;
+           tid = optarg;
+           prog = argv[optind++];
+           ipadd = argv[optind++];
+           port = argv[optind++];
+           break;
+         default:
+           usage++;
+           break;
+         }
+
+       if(optind + 1 != argc) {
+         usage++;
+       } else {
+         map = argv[optind];
+       }
+
+       if (usage) {
+               status = YPPUSH_BADARGS;
+               fprintf(stderr, "usage: %s %s %s\n",
+                   "[-cf] [-d domain] [-h host] [-s domain]",
+                   "[-C tid prog ipadd port] mapname\n",
+                   __progname);
+       }
+
+       if (status > 0) {
+               ypopenlog();
+
+               yplog("ypxfr: Arguments:");
+               yplog("YP clear to local: %s", (cflag) ? "no" : "yes");
+               yplog("   Force transfer: %s", (fflag) ? "yes" : "no");
+               yplog("           domain: %s", domain); 
+               yplog("             host: %s", host);
+               yplog("    source domain: %s", srcdomain);
+               yplog("          transid: %s", tid);
+               yplog("             prog: %s", prog);
+               yplog("             port: %s", port);
+               yplog("            ipadd: %s", ipadd);
+               yplog("              map: %s", map);
+
+               if(fflag != 0) {
+                       ordernum = 0;
+               } else {
+                       status = get_local_ordernum(domain, map, &ordernum);
+               }
+       }
+
+       if (status > 0) {
+
+               yplog("Get Master");
+
+               if (host == NULL) {
+                       if (srcdomain == NULL) {
+                               status = yp_master(domain,map,&host);
+                       } else {
+                               status = yp_master(srcdomain,map,&host);
+                       }
+                       if(status == 0) {
+                               status = YPPUSH_SUCC;
+                       } else {
+                               status = -status;
+                       }
+               }
+       };
+
+       /* XXX this is raceable if portmap has holes! */
+       if (status > 0) {
+               
+               yplog("Check for reserved port on host: %s", host); 
+
+               srvport = getrpcport(host,YPPROG,YPVERS,IPPROTO_TCP);
+               if (srvport >= IPPORT_RESERVED)
+                       status = YPPUSH_REFUSED;
+               
+       }
+
+       if (status > 0) {
+               
+               yplog("Connect host: %s", host); 
+
+               client = yp_bind_host(host,YPPROG,YPVERS,0,1);
+
+               status = get_remote_ordernum(client, domain, map,
+                                            ordernum, &new_ordernum);
+               
+       }
+
+       if (status == YPPUSH_SUCC) {
+               char    tmpmapname[MAXPATHLEN];
+               int     fd;
+
+               /* Create temporary db */
+               snprintf(tmpmapname, sizeof tmpmapname,
+                   "%s/%s/ypdbXXXXXXXXXX", YP_DB_PATH, domain);
+               fd = mkstemp(tmpmapname);
+               if (fd == -1)
+                       status = YPPUSH_DBM;
+               else
+                       close(fd);
+
+               if (status > 0) {
+                       db = create_db(domain,map,tmpmapname);
+                       if(db == NULL)
+                               status = YPPUSH_DBM;
+               }
+
+               /* Add ORDER */
+               if(status > 0) {
+                       status = add_order(db, new_ordernum);
+               }
+               
+               /* Add MASTER */
+               if(status > 0) {
+                       status = add_master(client,domain,map,db);
+               }
+               
+               /* Add INTERDOMAIN */
+               if(status > 0) {
+                       status = add_interdomain(client,domain,map,db);
+               }
+               
+               /* Add SECURE */
+               if(status > 0) {
+                       status = add_secure(client,domain,map,db);
+               }
+               
+               if(status > 0) {
+                       callback.foreach=ypxfr_foreach;
+                       get_map(client,domain,map,&callback);
+               }
+               
+               /* Close db */
+               if(db != NULL) {
+                       ypdb_close(db);
+               }
+
+               /* Rename db */
+               if(status > 0) {
+                       status = install_db(domain,map,tmpmapname);
+               } else {
+                       unlink(tmpmapname);
+                       status = YPPUSH_SUCC;
+               }
+               
+       }
+       
+       xfr_status = status;
+
+       if(client != NULL) {
+               clnt_destroy(client);
+       }
+
+       /* YP_CLEAR */
+
+       if(!cflag) {
+               client = yp_bind_local(YPPROG,YPVERS);
+               status = send_clear(client);
+               clnt_destroy(client);
+       }
+
+       if(Cflag > 0) {
+               /* Send Response */
+               client = yp_bind_host(ipadd,
+                                     atoi(prog),
+                                     1,
+                                     atoi(port),
+                                     0);
+               status = send_reply(client,xfr_status,atoi(tid));
+               clnt_destroy(client);
+       }
+
+       return(0);
+
+}
+
diff --git a/ypxfr.tproj/ypxfr_1perday.sh b/ypxfr.tproj/ypxfr_1perday.sh
new file mode 100755 (executable)
index 0000000..dab042c
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+#      $OpenBSD: ypxfr_1perday.sh,v 1.1 1997/04/20 10:08:36 maja Exp $
+#
+# ypxfr_1perday.sh - YP maps to be updated daily
+#
+
+/usr/sbin/ypxfr group.byname
+/usr/sbin/ypxfr group.bygid 
+/usr/sbin/ypxfr protocols.byname
+/usr/sbin/ypxfr protocols.bynumber
+/usr/sbin/ypxfr networks.byname
+/usr/sbin/ypxfr networks.byaddr
+/usr/sbin/ypxfr services.byname
+/usr/sbin/ypxfr rpc.bynumber
+/usr/sbin/ypxfr rpc.byname
diff --git a/ypxfr.tproj/ypxfr_1perhour.sh b/ypxfr.tproj/ypxfr_1perhour.sh
new file mode 100755 (executable)
index 0000000..82f43a2
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+#      $OpenBSD: ypxfr_1perhour.sh,v 1.1 1997/04/20 10:08:37 maja Exp $
+#
+# ypxfr_1perhour.sh - YP maps to be updated every hour
+#
+
+/usr/sbin/ypxfr passwd.byname
+/usr/sbin/ypxfr passwd.byuid 
+/usr/sbin/ypxfr master.passwd.byname
+/usr/sbin/ypxfr master.passwd.byuid 
+/usr/sbin/ypxfr netid.byname
diff --git a/ypxfr.tproj/ypxfr_2perday.sh b/ypxfr.tproj/ypxfr_2perday.sh
new file mode 100755 (executable)
index 0000000..0905270
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+#      $OpenBSD: ypxfr_2perday.sh,v 1.1 1997/04/20 10:08:38 maja Exp $
+#
+# ypxfr_2perday.sh - YP maps to be updated twice a day
+#
+
+/usr/sbin/ypxfr hosts.byname
+/usr/sbin/ypxfr hosts.byaddr
+/usr/sbin/ypxfr ethers.byaddr
+/usr/sbin/ypxfr ethers.byname
diff --git a/ypxfr.tproj/ypxfr_xdr.c b/ypxfr.tproj/ypxfr_xdr.c
new file mode 100644 (file)
index 0000000..460addf
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     $OpenBSD: ypxfr_xdr.c,v 1.3 1996/06/26 21:26:41 maja Exp $ */
+
+/*
+ * Copyright (c) 1995 Mats O Jansson <moj@stacken.kth.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Mats O Jansson
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LINT
+static char rcsid[] = "$OpenBSD: ypxfr_xdr.c,v 1.3 1996/06/26 21:26:41 maja Exp $";
+#endif
+
+
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp.h>
+
+bool_t
+xdr_ypxfrstat(xdrs, objp)
+       XDR *xdrs;
+       ypxfrstat *objp;
+{
+       if (!xdr_enum(xdrs, (enum_t *)objp)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+#ifdef notdef
+bool_t
+xdr_ypreq_xfr(xdrs, objp)
+       XDR *xdrs;
+       ypreq_xfr *objp;
+{
+       if (!xdr_ypmap_parms(xdrs, &objp->map_parms)) {
+               return (FALSE);
+       }
+       if (!xdr_u_int(xdrs, &objp->transid)) {
+               return (FALSE);
+       }
+       if (!xdr_u_int(xdrs, &objp->prog)) {
+               return (FALSE);
+       }
+       if (!xdr_u_int(xdrs, &objp->port)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+#endif
+
+bool_t
+xdr_ypresp_xfr(xdrs, objp)
+       XDR *xdrs;
+       ypresp_xfr *objp;
+{
+       if (!xdr_u_int(xdrs, &objp->transid)) {
+               return (FALSE);
+       }
+       if (!xdr_ypxfrstat(xdrs, &objp->xfrstat)) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+
+
+